Coverage Report

Created: 2026-06-13 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/gpsd/packet.c
Line
Count
Source
1
/****************************************************************************
2
3
NAME:
4
   packet.c -- a packet-sniffing engine for reading from GPS devices
5
6
DESCRIPTION:
7
8
Initial conditions of the problem:
9
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.
12
13
2. It may require more than one read to gather a packet.  Reads may span packet
14
   boundaries.
15
16
3. There may be leading garbage before the first packet.  After the first
17
   start-of-packet, the input should be well-formed.
18
19
The problem: how do we recognize which kind of packet we're getting?
20
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.
24
25
Tip of the hat to GitHub semuconsulting/pyspartn for showing how SPARTN works.
26
27
PERMISSIONS
28
   This file is Copyright by the GPSD project
29
   SPDX-License-Identifier: BSD-2-clause
30
31
***************************************************************************/
32
33
#include "../include/gpsd_config.h"  // must be before all includes
34
35
#include <arpa/inet.h>          // for htons()
36
#include <ctype.h>
37
#include <errno.h>
38
#include <netinet/in.h>
39
#include <stdbool.h>
40
#include <stdio.h>
41
#include <stdlib.h>             // for strtol()
42
#include <string.h>
43
#include <sys/time.h>           // for struct timeval
44
#include <sys/types.h>
45
#include <unistd.h>
46
47
#include "../include/bits.h"
48
#include "../include/driver_greis.h"
49
#include "../include/gpsd.h"
50
#include "../include/crc24q.h"
51
#include "../include/strfuncs.h"
52
53
/*
54
 * The packet-recognition state machine.  This takes an incoming byte stream
55
 * and tries to segment it into packets.  There are four types of packets:
56
 *
57
 * 1) Comments. These begin with # and end with \r\n.
58
 *
59
 * 2) NMEA lines.  These begin with $, and with \r\n, and have a checksum.
60
 *    Except $PASHR packets have no checksum!
61
 *
62
 * 3) Checksummed binary packets.  These begin with some fixed leader
63
 *    character(s), have a length embedded in them, and end with a
64
 *    checksum (and possibly some fixed trailing bytes).
65
 *
66
 * 4) ISGPS packets. The input may be a bitstream containing IS-GPS-200
67
 *    packets.  Each includes a fixed leader byte, a length, and check bits.
68
 *    In this case, it is not guaranteed that packet starts begin on byte
69
 *    boundaries; the recognizer has to run a separate state machine against
70
 *    each byte just to achieve synchronization lock with the bitstream.
71
 *
72
 * 5) Un-checksummed binary packets.  Like case 3, but without
73
 *    a checksum it's much easier to get a false match from garbage.
74
 *    The packet recognizer gives checksummed types higher priority.
75
 *
76
 * Adding support for a new GPS protocol typically requires adding state
77
 * transitions to support whatever binary packet structure it has.  The
78
 * goal is for the lexer to be able to cope with arbitrarily mixed packet
79
 * types on the input stream.  This is a requirement because (1) sometimes
80
 * gpsd wants to switch a device that supports both NMEA and a binary
81
 * packet protocol to the latter for more detailed reporting, and (b) in
82
 * the presence of device hotplugging, the type of GPS report coming
83
 * in is subject to change at any time.
84
 *
85
 * Caller should consume a packet when it sees one of the *_RECOGNIZED
86
 * states.  It's good practice to follow the _RECOGNIZED transition
87
 * with one that recognizes a leader of the same packet type rather
88
 * than dropping back to ground state -- this for example will prevent
89
 * the state machine from hopping between recognizing TSIP and
90
 * EverMore packets that both start with a DLE.
91
 *
92
 * Error handling is brutally simple; any time we see an unexpected
93
 * character, go to GROUND_STATE and reset the machine (except that a
94
 * $ in an NMEA payload only resets back to NMEA_DOLLAR state).  Because
95
 * another good packet will usually be along in less than a second
96
 * repeating the same data, Boyer-Moore-like attempts to do parallel
97
 * recognition beyond the headers would make no sense in this
98
 * application, they'd just add complexity.
99
 *
100
 * The NMEA portion of the state machine allows the following talker IDs:
101
 *      $BD -- Beidou
102
 *      $EC -- Electronic Chart Display & Information System (ECDIS)
103
 *      $GA -- Galileo
104
 *      $GB -- Beidou
105
 *      $GL -- GLONASS, according to IEIC 61162-1
106
 *      $GN -- Mixed GPS and GLONASS data, according to IEIC 61162-1
107
 *      $GP -- Global Positioning System.
108
 *      $GY -- Unicore Gyro
109
 *      $HC -- Heading/compass (Airmar PB200).
110
 *      $II -- Integrated Instrumentation (Raytheon's SeaTalk system).
111
 *      $IN -- Integrated Navigation (Garmin uses this).
112
 *      $P  -- Vendor-specific sentence
113
 *      $QZ -- QZSS GPS augmentation system
114
 *      $SD -- Depth Sounder
115
 *      $SN -- Unicore Sensor data
116
 *      $ST -- $STI, Skytraq Debug Output
117
 *      $TI -- Turn indicator (Airmar PB200).
118
 *      $WI -- Weather instrument (Airmar PB200, Radio Ocean ROWIND,
119
 *                                 Vaisala WXT520).
120
 *      $YX -- Transducer (used by some Airmar equipment including PB100)
121
 *
122
 *      !AB -- NMEA 4.0 Base AIS station
123
 *      !AD -- MMEA 4.0 Dependent AIS Base Station
124
 *      !AI -- Mobile AIS station
125
 *      !AN -- NMEA 4.0 Aid to Navigation AIS station
126
 *      !AR -- NMEA 4.0 AIS Receiving Station
127
 *      !AX -- NMEA 4.0 Repeater AIS station
128
 *      !AS -- NMEA 4.0 Limited Base Station
129
 *      !AT -- NMEA 4.0 AIS Transmitting Station
130
 *      !BS -- Base AIS station (deprecated in NMEA 4.0)
131
 *      !SA -- NMEA 4.0 Physical Shore AIS Station
132
 */
133
134
enum
135
{
136
#include "../include/packet_states.h"
137
};
138
139
static char *state_table[] = {
140
#include "../include/packet_names.h"
141
};
142
143
308k
#define SOH     (unsigned char)0x01
144
24.7M
#define DLE     (unsigned char)0x10
145
2.10M
#define STX     (unsigned char)0x02
146
138k
#define ETX     (unsigned char)0x03
147
1.50M
#define MICRO   (unsigned char)0xb5
148
149
#if defined(TSIP_ENABLE)
150
// Maximum length a TSIP packet can be
151
606k
#define TSIP_MAX_PACKET 255
152
#endif
153
154
unsigned casic_checksum(unsigned char *buf, size_t len)
155
8.00k
{
156
    // CASIC uses a 32 bit little-endian checksum
157
    // All payloads sizes are 4-byte aligned
158
8.00k
    size_t idx;
159
8.00k
    unsigned crc_computed = 0;
160
161
32.1k
    for (idx = 0; idx < len; idx += 4) {
162
24.0k
        crc_computed += getleu32(buf, idx);
163
24.0k
    }
164
8.00k
    return crc_computed;
165
8.00k
}
166
167
#ifdef ONCORE_ENABLE
168
static size_t oncore_payload_cksum_length(unsigned char id1, unsigned char id2)
169
660k
{
170
660k
    size_t l;
171
172
    /* For the packet sniffer to not terminate the message due to
173
     * payload data looking like a trailer, the known payload lengths
174
     * including the checksum are given.  Return -1 for unknown IDs.
175
     */
176
177
945k
#define ONCTYPE(id2,id3) ((((unsigned int)id2) << 8) | (id3))
178
179
660k
    switch (ONCTYPE(id1,id2)) {
180
    // A...
181
569
    case ONCTYPE('A','a'):
182
        // time of day
183
569
        l = 10;
184
569
        break;
185
734
    case ONCTYPE('A','b'):
186
        // GMT offset
187
734
        l = 10;
188
734
        break;
189
1.04k
    case ONCTYPE('A','c'):
190
        // date
191
1.04k
        l = 11;
192
1.04k
        break;
193
1.28k
    case ONCTYPE('A','d'):
194
        // latitude
195
1.28k
        l = 11;
196
1.28k
        break;
197
1.02k
    case ONCTYPE('A','e'):
198
        // longitude
199
1.02k
        l = 11;
200
1.02k
        break;
201
2.00k
    case ONCTYPE('A','f'):
202
        // height
203
2.00k
        l = 15;
204
2.00k
        break;
205
545
    case ONCTYPE('A','g'):
206
        // satellite mask angle
207
545
        l = 8;
208
545
        break;
209
    // Command "Ao" gives "Ap" response (select datum)
210
623
    case ONCTYPE('A','p'):
211
        // set user datum / select datum
212
623
        l = 25;
213
623
        break;
214
721
    case ONCTYPE('A','q'):
215
        // atmospheric correction mode
216
721
        l = 8;
217
721
        break;
218
1.59k
    case ONCTYPE('A','s'):
219
        // position-hold position
220
1.59k
        l = 20;
221
1.59k
        break;
222
1.66k
    case ONCTYPE('A','t'):
223
        // position-hold mode
224
1.66k
        l = 8;
225
1.66k
        break;
226
657
    case ONCTYPE('A','u'):
227
        // altitude hold height
228
657
        l = 12;
229
657
        break;
230
675
    case ONCTYPE('A','v'):
231
        // altitude hold mode
232
675
        l = 8;
233
675
        break;
234
1.88k
    case ONCTYPE('A','w'):
235
        // time mode
236
1.88k
        l = 8;
237
1.88k
        break;
238
2.27k
    case ONCTYPE('A','y'):
239
        // 1PPS offset
240
2.27k
        l = 11;
241
2.27k
        break;
242
2.01k
    case ONCTYPE('A','z'):
243
        // 1PPS cable delay
244
2.01k
        l = 11;
245
2.01k
        break;
246
1.17k
    case ONCTYPE('A','N'):
247
        // velocity filter
248
1.17k
        l = 8;
249
1.17k
        break;
250
16.9k
    case ONCTYPE('A','O'):
251
        // RTCM report mode
252
16.9k
        l = 8;
253
16.9k
        break;
254
224k
    case ONCTYPE('A','P'):
255
        // pulse mode
256
224k
        l = 8;
257
224k
        break;
258
259
    // B...
260
1.59k
    case ONCTYPE('B','b'):
261
        // visible satellites status
262
1.59k
        l = 92;
263
1.59k
        break;
264
620
    case ONCTYPE('B','j'):
265
        // leap seconds pending
266
620
        l = 8;
267
620
        break;
268
1.61k
    case ONCTYPE('B','o'):
269
        // UTC offset status
270
1.61k
        l = 8;
271
1.61k
        break;
272
273
    // C...
274
888
    case ONCTYPE('C','b'):
275
        // almanac output ("Be" response)
276
888
        l = 33;
277
888
        break;
278
644
    case ONCTYPE('C','c'):
279
        // ephemeris data input ("Bf")
280
644
        l = 80;
281
644
        break;
282
2.09k
    case ONCTYPE('C','f'):
283
        // set-to-defaults
284
2.09k
        l = 7;
285
2.09k
        break;
286
    // Command "Ci" (switch to NMEA, GT versions only) has no response
287
581
    case ONCTYPE('C','h'):
288
        // almanac input ("Cb" response)
289
581
        l = 9;
290
581
        break;
291
716
    case ONCTYPE('C','j'):
292
        // receiver ID
293
716
        l = 294;
294
716
        break;
295
962
    case ONCTYPE('C','k'):
296
        // pseudorng correction inp. ("Ce")
297
962
        l = 7;
298
962
        break;
299
300
    // E...
301
3.55k
    case ONCTYPE('E','a'):
302
        // position/status/data
303
3.55k
        l = 76;
304
3.55k
        break;
305
1.60k
    case ONCTYPE('E','n'):
306
        // time RAIM setup and status
307
1.60k
        l = 69;
308
1.60k
        break;
309
629
    case ONCTYPE('E','q'):
310
        // ASCII position
311
629
        l = 96;
312
629
        break;
313
314
    // F...
315
758
    case ONCTYPE('F','a'):
316
        // self-test
317
758
        l = 9;
318
758
        break;
319
320
    // G...
321
1.65k
    case ONCTYPE('G','d'):
322
        // position hold or survey
323
1.65k
        l = 8;
324
1.65k
        break;
325
1.19k
    case ONCTYPE('G','e'):
326
        // T-RAIM enable
327
1.19k
        l = 8;
328
1.19k
        break;
329
    // H...
330
2.15k
    case ONCTYPE('H','a'):
331
        // position/status/data
332
2.15k
        l = 154;
333
2.15k
        break;
334
335
    // S...
336
1.10k
    case ONCTYPE('S','z'):
337
        // system power-on failure
338
1.10k
        l = 8;
339
1.10k
        break;
340
341
375k
    default:
342
375k
        return 0;
343
660k
    }
344
345
284k
    return l - 6;               // Subtract header and trailer.
346
660k
}
347
#endif  // ONCORE_ENABLE
348
349
#ifdef GREIS_ENABLE
350
351
// Convert hex char to binary form. Requires that c be a hex char.
352
static unsigned long greis_hex2bin(char c)
353
158k
{
354
158k
    if (('a' <= c) &&
355
6.16k
        ('f' >= c)) {
356
6.16k
        c = c + 10 - 'a';
357
152k
    } else if (('A' <= c) &&
358
51.5k
               ('F' >= c)) {
359
51.5k
        c = c + 10 - 'A';
360
101k
    } else if (('0' <= c) &&
361
101k
               ('9' >= c)) {
362
101k
        c -= '0';
363
101k
    }
364
    // FIXME: No error handling?
365
366
158k
    return c;
367
158k
}
368
369
#endif  // GREIS_ENABLE
370
371
/* nmea_checksum(*errout, buf) -- check NMEA checksum for message in buffer.
372
 * Also handles !AI checksums.
373
 *
374
 * Return: True = Checksum good
375
 *         False -- checksum bad
376
 */
377
static bool nmea_checksum(const struct gpsd_errout_t *errout,
378
                          const char *buf, const char *endp)
379
128k
{
380
128k
    bool checksum_ok = true;
381
128k
    const char *end;
382
128k
    unsigned n, csum = 0;
383
128k
    char csum_s[3] = { '0', '0', '0' };
384
385
    /* These have no checksum:
386
     *  GPS-320FW emits $PLCS
387
     *  MTK-3301 emits $POLYN
388
     *  Skytraq S2525F8-BD-RTK emits $STI
389
     *  Telit SL869 emits $GPTXT
390
     *  Ashtech (old!) $PASHR,MCA and $PASHR,PBN with no checksum
391
     * All undocumented,  Let them fail, except $STI.
392
     */
393
128k
    if (str_starts_with(buf, "$STI,")) {
394
        // Let this one go...
395
6.62k
        return true;
396
6.62k
    }
397
398
    /* Some messages, like !AIVMD, !AIVMO, can have "stuff" after the
399
     * checksum.  Some messages can have "*" in the body of a message.
400
     * At least one GPS (the Firefly 1a) emits \r\r\n at the end.
401
     *
402
     * So scan backwards until we find the *.  Use the 2 chars to the
403
     * right as the checksum.
404
     */
405
843k
    for (end = endp - 1; buf < end; end--) {
406
834k
        if ('*' == *end) {
407
112k
            break;
408
112k
        }
409
834k
    }
410
411
121k
    if ('*' != *end) {
412
        // no asterisk found
413
9.11k
        return false;
414
9.11k
    }
415
416
112k
    if (end + 2 >= endp) {
417
        // not enough room for the two-hex-digit checksum
418
2.17k
        return false;
419
2.17k
    }
420
421
    /* Verify checksum is 2 hex digits.  Irnoge trailing stuff.
422
     * Magellan EC-10X has lower case hex in checksum. It is rare.  */
423
110k
    if (!isxdigit((unsigned char) end[1]) ||
424
109k
        !isxdigit((unsigned char) end[2])) {
425
2.54k
        return false;
426
2.54k
    }
427
428
    // compute the checksum
429
4.42M
    for (n = 1; buf + n < end; n++) {
430
4.31M
        csum ^= buf[n];
431
4.31M
    }
432
107k
    (void)snprintf(csum_s, sizeof(csum_s), "%02X", csum);
433
107k
    checksum_ok = (csum_s[0] == toupper((int)end[1]) &&
434
94.3k
                   csum_s[1] == toupper((int)end[2]));
435
107k
    if (!checksum_ok) {
436
17.6k
        GPSD_LOG(LOG_WARN, errout,
437
17.6k
                 "bad checksum in NMEA packet; got %c%c expected %s.\n",
438
17.6k
                 end[1], end[2], csum_s);
439
17.6k
    }
440
441
107k
    return checksum_ok;
442
110k
}
443
444
// Convert SPARTN TF015 (Embedded Auth Len) to bytes
445
static unsigned spartn_auth_len(unsigned index)
446
0
{
447
    // 5 to 7 TBD
448
0
    static unsigned id2len[] = {8, 12, 16, 32, 64, 0, 0, 0};
449
450
0
    return id2len[index & 7];
451
0
}
452
453
// push back the last character grabbed, setting a specified state
454
static bool character_pushback(struct gps_lexer_t *lexer,
455
                               unsigned int newstate)
456
163M
{
457
163M
    --lexer->inbufptr;
458
163M
    --lexer->char_counter;
459
163M
    lexer->state = newstate;
460
163M
    if (lexer->errout.debug >= LOG_RAW2) {
461
0
        unsigned char c = *lexer->inbufptr;
462
463
0
        GPSD_LOG(LOG_RAW, &lexer->errout,
464
0
                 "%08ld: character '%c' [%02x]  pushed back, state set to %s\n",
465
0
                 lexer->char_counter,
466
0
                 (isprint((int)c) ? c : '.'), c,
467
0
                 state_table[lexer->state]);
468
0
    }
469
470
163M
    return false;
471
163M
}
472
473
// shift the input buffer to discard one character and reread data
474
static void character_discard(struct gps_lexer_t *lexer)
475
11.9M
{
476
11.9M
    memmove(lexer->inbuffer, lexer->inbuffer + 1, (size_t)-- lexer->inbuflen);
477
11.9M
    lexer->inbufptr = lexer->inbuffer;
478
11.9M
    if (lexer->errout.debug >= LOG_RAW1) {
479
0
        char scratchbuf[MAX_PACKET_LENGTH*4+1];
480
481
0
        GPSD_LOG(LOG_RAW1, &lexer->errout,
482
0
                 "Character discarded, buffer %zu chars = %s\n",
483
0
                 lexer->inbuflen,
484
0
                 gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
485
0
                                 lexer->inbuffer, lexer->inbuflen));
486
0
    }
487
11.9M
}
488
489
/* get 0-origin big-endian words relative to start of packet buffer
490
 * used for Zodiac */
491
2.46k
#define getzuword(i) (unsigned)(lexer->inbuffer[2 * (i)] | \
492
2.46k
                                (lexer->inbuffer[2 * (i) + 1] << 8))
493
211k
#define getzword(i) (short)(lexer->inbuffer[2 * (i)] | \
494
211k
                           (lexer->inbuffer[2 * (i) + 1] << 8))
495
496
static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
497
613M
{
498
613M
    static int n = 0;
499
613M
    enum isgpsstat_t isgpsstat;
500
613M
#ifdef SUPERSTAR2_ENABLE
501
613M
    static unsigned char ctmp;
502
613M
#endif  // SUPERSTAR2_ENABLE
503
504
613M
    n++;
505
613M
    switch (lexer->state) {
506
174M
    case GROUND_STATE:
507
174M
        n = 0;
508
174M
#ifdef STASH_ENABLE
509
174M
        lexer->stashbuflen = 0;
510
174M
#endif
511
174M
        switch (c) {
512
0
#ifdef SUPERSTAR2_ENABLE
513
304k
        case SOH:          // 0x01
514
304k
            lexer->state = SUPERSTAR2_LEADER;
515
304k
            break;
516
0
#endif // SUPERSTAR2_ENABLE
517
0
#ifdef NAVCOM_ENABLE
518
1.69M
        case STX:          // 0x02
519
1.69M
            lexer->state = NAVCOM_LEADER_1;
520
1.69M
            break;
521
0
#endif  // NAVCOM_ENABLE
522
0
#if defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(GARMIN_ENABLE)
523
363k
        case DLE:          // 0x10
524
363k
            lexer->state = DLE_LEADER;
525
363k
            break;
526
0
#endif  // TSIP_ENABLE || EVERMORE_ENABLE || GARMIN_ENABLE
527
751k
        case '!':
528
751k
            lexer->state = AIS_BANG;
529
751k
            break;
530
313k
        case '#':
531
313k
            lexer->state = COMMENT_BODY;
532
313k
            break;
533
294k
        case '$':
534
294k
            lexer->state = NMEA_DOLLAR;
535
294k
            break;
536
0
#if defined(TNT_ENABLE) || defined(GARMINTXT_ENABLE) || defined(ONCORE_ENABLE)
537
83.3M
        case '@':
538
83.3M
            if (ISGPS_MESSAGE == rtcm2_decode(lexer, c)) {
539
6.74k
                lexer->state = RTCM2_RECOGNIZED;
540
6.74k
                break;
541
6.74k
            }
542
83.2M
            lexer->state = AT1_LEADER;
543
83.2M
            break;
544
0
#endif // TNT_ENABLE, GARMINTXT_ENABLE, ONCORE_ENABLE
545
0
#ifdef ITRAX_ENABLE
546
408k
        case '<':
547
408k
            lexer->state = ITALK_LEADER_1;
548
408k
            break;
549
0
#endif  // ITRAX_ENABLE
550
0
#ifdef TRIPMATE_ENABLE
551
239k
        case 'A':
552
239k
            if (ISGPS_MESSAGE == rtcm2_decode(lexer, c)) {
553
368
                lexer->state = RTCM2_RECOGNIZED;
554
368
                break;
555
368
            }
556
239k
            lexer->state = ASTRAL_1;
557
239k
            break;
558
0
#endif  // TRIPMATE_ENABLE
559
0
#ifdef EARTHMATE_ENABLE
560
105k
        case 'E':
561
105k
            if (ISGPS_MESSAGE == rtcm2_decode(lexer, c)) {
562
450
                lexer->state = RTCM2_RECOGNIZED;
563
450
                break;
564
450
            }
565
105k
            lexer->state = EARTHA_1;
566
105k
            break;
567
0
#endif  // EARTHMATE_ENABLE
568
0
#ifdef GEOSTAR_ENABLE
569
602k
        case 'P':
570
602k
            lexer->state = GEOSTAR_LEADER_1;
571
602k
            break;
572
0
#endif  // GEOSTAR_ENABLE
573
0
#ifdef GREIS_ENABLE
574
434k
        case 'R':
575
434k
            lexer->state = GREIS_REPLY_1;
576
434k
            break;
577
0
#endif  // GREIS_ENABLE
578
165k
        case '{':
579
165k
            return character_pushback(lexer, JSON_LEADER);
580
0
#ifdef GREIS_ENABLE
581
        // Tilda, Not the only possibility, but a distinctive cycle starter.
582
438k
        case '~':
583
438k
            lexer->state = GREIS_ID_1;
584
438k
            break;
585
0
#endif  // GREIS_ENABLE
586
0
#if defined(SIRF_ENABLE) || defined(SKYTRAQ_ENABLE)
587
1.30M
        case 0xa0:     // latin1 non breaking space
588
1.30M
            lexer->state = SIRF_LEADER_1;
589
1.30M
            break;
590
0
#endif  // SIRF_ENABLE || SKYTRAQ_ENABLE
591
1.41M
        case MICRO:      // latin1 micro, 0xb5
592
1.41M
            lexer->state = UBX_LEADER_1;
593
1.41M
            break;
594
273k
        case 0xba:      // latin1 MASCULINE ORDINAL INDICATOR
595
            // got 1st, of 2, bytes of leader
596
273k
            lexer->state = CASIC_LEADER_1;
597
273k
            break;
598
70.7M
        case 0xD3:      // latin1 capital O acute
599
70.7M
            lexer->state = RTCM3_LEADER_1;
600
70.7M
            break;
601
361k
        case 0xf1:      // latin1 small letter N with tilde
602
            // got 1st, of 2, bytes of leader
603
361k
            lexer->state = ALLY_LEADER_1;
604
361k
            break;
605
0
#ifdef ZODIAC_ENABLE
606
811k
        case 0xff:      // lattin1 small y with diaeresis
607
811k
            lexer->state = ZODIAC_LEADER_1;
608
811k
            break;
609
0
#endif  // ZODIAC_ENABLE
610
34.1k
        case 's':
611
            // SPARTN, 0x73
612
34.1k
            if (0 ==
613
34.1k
                (lexer->type_mask & PACKET_TYPEMASK(SPARTN_PACKET))) {
614
0
                lexer->state = SPARTN_PRE_1;
615
0
                GPSD_LOG(LOG_IO, &lexer->errout, "SPARTN 0x73\n");
616
0
                break;
617
0
            }  // else
618
34.1k
            FALLTHROUGH
619
10.1M
        default:
620
10.1M
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
621
16.2k
                lexer->state = RTCM2_SYNC_STATE;
622
10.1M
            } else if (ISGPS_MESSAGE == isgpsstat) {
623
726
                lexer->state = RTCM2_RECOGNIZED;
624
726
            }
625
10.1M
            break;
626
174M
        }
627
174M
        break;
628
174M
    case COMMENT_BODY:
629
1.05M
        if ('\n' == c) {
630
11.2k
            lexer->state = COMMENT_RECOGNIZED;
631
1.03M
        } else if ('\r' == c ||
632
1.03M
                   '\t' == c) {
633
            // allow tabs and CR in comments
634
1.03M
        } else if (!isprint(c)) {
635
306k
            GPSD_LOG(LOG_RAW, &lexer->errout, "COMMENT: x%x\n", c);
636
306k
            return character_pushback(lexer, GROUND_STATE);
637
306k
        }
638
744k
        break;
639
744k
    case NMEA_DOLLAR:
640
        // We have the leading $
641
331k
        switch (c) {
642
24.2k
        case 'A':
643
            /* $A (SiRF Ack), $AI (Mobile Class A or B AIS Station?), or
644
             * $AP (autopliot) */
645
24.2k
            lexer->state = NMEA_LEAD_A;
646
24.2k
            break;
647
5.11k
        case 'B':           // $BD
648
5.11k
            lexer->state = BEIDOU_LEAD_1;
649
5.11k
            break;
650
4.06k
        case 'E':           // $E, ECDIS
651
            // codacy thinks this is impossible
652
4.06k
            lexer->state = ECDIS_LEAD_1;
653
4.06k
            break;
654
70.6k
        case 'G':           // $GP, $GN, $GY, etc.
655
70.6k
            lexer->state = NMEA_PUB_LEAD;
656
70.6k
            break;
657
10.1k
        case 'H':           // $H, Heading/compass. gyro
658
10.1k
            lexer->state = HEADCOMP_LEAD_1;
659
10.1k
            break;
660
6.45k
        case 'I':           // $I, Seatalk
661
6.45k
            lexer->state = SEATALK_LEAD_1;
662
6.45k
            break;
663
84.2k
        case 'P':           // $P, vendor sentence
664
84.2k
            lexer->state = NMEA_VENDOR_LEAD;
665
84.2k
            break;
666
2.60k
        case 'Q':          // $QZ
667
2.60k
            lexer->state = QZSS_LEAD_1;
668
2.60k
            break;
669
28.1k
        case 'S':          // $S
670
            // $SD, $SN, $ST
671
28.1k
            lexer->state = SOUNDER_LEAD_1;
672
28.1k
            break;
673
3.07k
        case 'T':           // $T, Turn indicator
674
3.07k
            lexer->state = TURN_LEAD_1;
675
3.07k
            break;
676
2.30k
        case 'W':           // $W, Weather instrument
677
2.30k
            lexer->state = WEATHER_LEAD_1;
678
2.30k
            break;
679
2.16k
        case 'Y':           // $Y
680
2.16k
            lexer->state = TRANSDUCER_LEAD_1;
681
2.16k
            break;
682
88.1k
        default:
683
88.1k
            (void)character_pushback(lexer, GROUND_STATE);
684
88.1k
            break;
685
331k
        }
686
331k
        break;
687
331k
    case NMEA_PUB_LEAD:
688
        /*
689
         * $GP == GPS, $GL = GLONASS only, $GN = mixed GPS and GLONASS,
690
         * according to NMEA (IEIC 61162-1) DRAFT 02/06/2009.
691
         * We have a log from China with a BeiDou device using $GB
692
         * rather than $BD.
693
         *
694
         * Unicore uses the non-standard $GY for IMU data.
695
         */
696
70.6k
        if ('A' == c ||      // $GA, Galileo only
697
68.0k
            'B' == c ||      // $GB, BeiDou only
698
64.0k
            'L' == c ||      // $GL, GLONASS only
699
60.9k
            'N' == c ||      // $GN, mixed
700
55.3k
            'P' == c ||      // $GP, GPS
701
62.1k
            'Y' == c) {      // $GY, Gyro  (IMU)
702
62.1k
            lexer->state = NMEA_LEADER_END;
703
62.1k
        } else {
704
8.46k
            (void)character_pushback(lexer, GROUND_STATE);
705
8.46k
        }
706
70.6k
        break;
707
84.2k
    case NMEA_VENDOR_LEAD:
708
84.2k
        if ('A' == c) {            // $PA
709
16.7k
            lexer->state = NMEA_PASHR_A;
710
67.5k
        } else if (isalpha(c)) {
711
59.9k
            lexer->state = NMEA_LEADER_END;
712
59.9k
        } else {
713
7.53k
            (void) character_pushback(lexer, GROUND_STATE);
714
7.53k
        }
715
84.2k
        break;
716
    /*
717
     * Without the following six states (NMEA_PASH_*, NMEA_BINARY_*)
718
     * DLE in a $PASHR can fool the  sniffer into thinking it sees a
719
     * TSIP packet.  Hilarity ensues.
720
     */
721
16.7k
    case NMEA_PASHR_A:
722
16.7k
        if ('S' == c) {        // $PAS
723
9.50k
            lexer->state = NMEA_PASHR_S;
724
9.50k
        } else if (isalpha(c)) {
725
5.56k
            lexer->state = NMEA_LEADER_END;
726
5.56k
        } else {
727
1.66k
            (void)character_pushback(lexer, GROUND_STATE);
728
1.66k
        }
729
16.7k
        break;
730
9.50k
    case NMEA_PASHR_S:
731
9.50k
        if ('H' == c) {        // $PASH
732
8.08k
            lexer->state = NMEA_PASHR_H;
733
8.08k
        } else if (isalpha(c)) {
734
781
            lexer->state = NMEA_LEADER_END;
735
781
        } else {
736
638
            (void)character_pushback(lexer, GROUND_STATE);
737
638
        }
738
9.50k
        break;
739
8.08k
    case NMEA_PASHR_H:
740
8.08k
        if ('R' == c) {         // $PASHR
741
6.47k
            lexer->state = NMEA_BINARY_BODY;
742
6.47k
        } else if (isalpha(c)) {
743
791
            lexer->state = NMEA_LEADER_END;
744
813
        } else {
745
813
            (void) character_pushback(lexer, GROUND_STATE);
746
813
        }
747
8.08k
        break;
748
516k
    case NMEA_BINARY_BODY:
749
516k
        if ('\r' == c) {
750
14.4k
            lexer->state = NMEA_BINARY_CR;
751
14.4k
        }
752
516k
        break;
753
14.4k
    case NMEA_BINARY_CR:
754
14.4k
        if (c == '\n') {
755
10.3k
            lexer->state = NMEA_BINARY_NL;
756
10.3k
        } else {
757
4.16k
            lexer->state = NMEA_BINARY_BODY;
758
4.16k
        }
759
14.4k
        break;
760
10.2k
    case NMEA_BINARY_NL:
761
10.2k
        if ('$' == c) {
762
6.21k
            (void)character_pushback(lexer, NMEA_RECOGNIZED);
763
6.21k
        } else {
764
4.06k
            lexer->state = NMEA_BINARY_BODY;
765
4.06k
        }
766
10.2k
        break;
767
    // end PASHR, TSIP mitigation
768
769
    // start of AIS states
770
753k
    case AIS_BANG:
771
753k
        if ('A' == c) {          // !A
772
44.3k
            lexer->state = AIS_LEAD_1;
773
708k
        } else if ('B' == c) {   // !B
774
7.98k
            lexer->state = AIS_LEAD_ALT1;
775
700k
        } else if ('S' == c) {   // !S
776
7.18k
            lexer->state = AIS_LEAD_ALT3;
777
693k
        } else {
778
693k
            return character_pushback(lexer, GROUND_STATE);
779
693k
        }
780
59.5k
        break;
781
59.5k
    case AIS_LEAD_1:
782
44.3k
        if (NULL != strchr("BDINRSTX", c)) {
783
            // !AB, !AD, !AI, !AN, !AR, !AS, !AT, !AX
784
30.3k
            lexer->state = AIS_LEAD_2;
785
30.3k
        } else {
786
13.9k
            return character_pushback(lexer, GROUND_STATE);
787
13.9k
        }
788
30.3k
        break;
789
45.8k
    case AIS_LEAD_2:
790
45.8k
        if (isalpha(c)) {
791
42.6k
            lexer->state = AIS_LEADER_END;
792
42.6k
        } else {
793
3.25k
            return character_pushback(lexer, GROUND_STATE);
794
3.25k
        }
795
42.6k
        break;
796
42.6k
    case AIS_LEAD_ALT1:
797
7.98k
        if ('S' == c) {
798
            // !BS
799
3.54k
            lexer->state = AIS_LEAD_ALT2;
800
4.43k
        } else {
801
4.43k
            return character_pushback(lexer, GROUND_STATE);
802
4.43k
        }
803
3.54k
        break;
804
3.54k
    case AIS_LEAD_ALT2:
805
3.54k
        if (isalpha(c)) {
806
1.25k
            lexer->state = AIS_LEADER_END;
807
2.29k
        } else {
808
2.29k
            return character_pushback(lexer, GROUND_STATE);
809
2.29k
        }
810
1.25k
        break;
811
7.18k
    case AIS_LEAD_ALT3:
812
7.18k
        if ('A' == c) {
813
            // !SA
814
4.02k
            lexer->state = AIS_LEAD_ALT4;
815
4.02k
        } else {
816
3.15k
            return character_pushback(lexer, GROUND_STATE);
817
3.15k
        }
818
4.02k
        break;
819
4.02k
    case AIS_LEAD_ALT4:
820
4.02k
        if (isalpha(c)) {
821
2.41k
            lexer->state = AIS_LEADER_END;
822
2.41k
        } else {
823
1.60k
            return character_pushback(lexer, GROUND_STATE);
824
1.60k
        }
825
2.41k
        break;
826
1.79M
    case AIS_LEADER_END:
827
        // We stay here grabbing the body of the message, until \r\n
828
1.79M
        if ('\r' == c) {
829
12.8k
            lexer->state = AIS_CR;
830
1.77M
        } else if ('\n' == c) {
831
            /* not strictly correct (missing \r), but helps with
832
             * interpreting logfiles. */
833
16.2k
            lexer->state = AIS_RECOGNIZED;
834
1.76M
        } else if (!isprint(c)) {
835
16.9k
            (void)character_pushback(lexer, GROUND_STATE);
836
16.9k
        }
837
1.79M
        break;
838
12.8k
    case AIS_CR:
839
12.8k
        if ('\n' == c) {
840
11.6k
            lexer->state = AIS_RECOGNIZED;
841
11.6k
        } else {
842
1.25k
            (void)character_pushback(lexer, GROUND_STATE);
843
1.25k
        }
844
12.8k
        break;
845
    // end of AIS states
846
847
0
#if defined(TNT_ENABLE) || defined(GARMINTXT_ENABLE) || defined(ONCORE_ENABLE)
848
85.9M
    case AT1_LEADER:
849
85.9M
        switch (c) {
850
0
#ifdef ONCORE_ENABLE
851
82.8M
        case '@':
852
82.8M
            lexer->state = ONCORE_AT2;
853
82.8M
            break;
854
0
#endif  // ONCORE_ENABLE
855
0
#ifdef TNT_ENABLE
856
21.7k
        case '*':
857
            /*
858
             * TNT has similar structure to NMEA packet, '*' before
859
             * optional checksum ends the packet. Since '*' cannot be
860
             * received from GARMIN working in TEXT mode, use this
861
             * difference to tell that this is not GARMIN TEXT packet,
862
             * could be TNT.
863
             */
864
21.7k
            lexer->state = NMEA_LEADER_END;
865
21.7k
            break;
866
0
#endif  // TNT_ENABLE
867
#if defined(GARMINTXT_ENABLE)
868
        case '\r':
869
            /* stay in this state, next character should be '\n'
870
             * in the theory we can stop search here and don't wait for '\n' */
871
            lexer->state = AT1_LEADER;
872
            break;
873
        case '\n':
874
            // end of packet found
875
            lexer->state = GTXT_RECOGNIZED;
876
            break;
877
#endif  // GARMINTXT_ENABLE
878
3.10M
        default:
879
3.10M
            if (!isprint(c)) {
880
478k
                return character_pushback(lexer, GROUND_STATE);
881
478k
            }
882
85.9M
        }
883
85.4M
        break;
884
85.4M
#endif  // TNT_ENABLE || GARMINTXT_ENABLE || ONCORE_ENABLE
885
85.4M
    case NMEA_LEADER_END:
886
        // We stay here grabbing the body of the message
887
4.16M
        if ('\r' == c) {
888
62.7k
            lexer->state = NMEA_CR;
889
4.10M
        } else if ('\n' == c) {
890
            /* not strictly correct (missing \r), but helps with
891
             * interpreting logfiles. */
892
32.4k
            lexer->state = NMEA_RECOGNIZED;
893
4.07M
        } else if ('$' == c) {
894
17.9k
#ifdef STASH_ENABLE
895
17.9k
            (void)character_pushback(lexer, STASH_RECOGNIZED);
896
#else
897
            (void)character_pushback(lexer, GROUND_STATE);
898
#endif
899
4.05M
        } else if (!isprint(c)) {
900
77.9k
            (void)character_pushback(lexer, GROUND_STATE);
901
77.9k
        }
902
4.16M
        break;
903
76.4k
    case NMEA_CR:
904
76.4k
        if ('\n' == c) {
905
58.6k
            lexer->state = NMEA_RECOGNIZED;
906
58.6k
        } else if ('\r' == c) {
907
            /*
908
             * There's a GPS called a Jackson Labs Firefly-1a that emits \r\r\n
909
             * at the end of each sentence.  Don't be confused by this.
910
             */
911
13.7k
            lexer->state = NMEA_CR;
912
13.7k
        } else {
913
4.06k
            (void)character_pushback(lexer, GROUND_STATE);
914
4.06k
        }
915
76.4k
        break;
916
21.5k
    case AIS_RECOGNIZED:
917
        // AIS and NMEA often mixed treat them similar to start
918
21.5k
        FALLTHROUGH
919
93.8k
    case NMEA_RECOGNIZED:
920
93.8k
        if ('#' == c) {
921
3.01k
            lexer->state = COMMENT_BODY;
922
90.8k
        } else if ('$' == c) {
923
            // codacy thinks this state is impossible
924
17.1k
            lexer->state = NMEA_DOLLAR;
925
73.7k
        } else if ('!' == c) {
926
2.41k
            lexer->state = AIS_BANG;
927
71.3k
        } else if (MICRO == c) {   // latin1 micro, 0xb5
928
            // LEA-5H can/will output NMEA/UBX back to back
929
            // codacy says this state impossible?
930
947
            lexer->state = UBX_LEADER_1;
931
70.3k
        } else if ('{' == c) {
932
            // codacy says this state impossible?
933
2.40k
            return character_pushback(lexer, JSON_LEADER);
934
67.9k
        } else {
935
67.9k
            return character_pushback(lexer, GROUND_STATE);
936
67.9k
        }
937
23.4k
        break;
938
23.4k
    case SEATALK_LEAD_1:
939
6.45k
        if ('I' == c ||
940
5.93k
            'N' == c) {         // $II or $IN are accepted
941
5.00k
            lexer->state = NMEA_LEADER_END;
942
5.00k
        } else {
943
1.44k
            return character_pushback(lexer, GROUND_STATE);
944
1.44k
        }
945
5.00k
        break;
946
5.00k
    case WEATHER_LEAD_1:
947
2.29k
        if ('I' == c) {         // $WI, Weather instrument leader accepted
948
1.23k
            lexer->state = NMEA_LEADER_END;
949
1.23k
        } else {
950
1.06k
            return character_pushback(lexer, GROUND_STATE);
951
1.06k
        }
952
1.23k
        break;
953
10.1k
    case HEADCOMP_LEAD_1:
954
10.1k
        if ('C' == c ||         // $HC, Heading/compass leader accepted
955
5.59k
            'E' == c) {         // $HE, Gyro, north seeking
956
5.59k
            lexer->state = NMEA_LEADER_END;
957
5.59k
        } else {
958
4.53k
            return character_pushback(lexer, GROUND_STATE);
959
4.53k
        }
960
5.59k
        break;
961
5.59k
    case TURN_LEAD_1:
962
3.07k
        if ('I' == c) {           // $TI, Turn indicator leader accepted
963
859
            lexer->state = NMEA_LEADER_END;
964
2.21k
        } else {
965
2.21k
            return character_pushback(lexer, GROUND_STATE);
966
2.21k
        }
967
859
        break;
968
4.06k
    case ECDIS_LEAD_1:
969
4.06k
        if ('C' == c) {           // $EC, ECDIS leader accepted
970
626
            lexer->state = NMEA_LEADER_END;
971
3.44k
        } else {
972
3.44k
            return character_pushback(lexer, GROUND_STATE);
973
3.44k
        }
974
626
        break;
975
28.1k
    case SOUNDER_LEAD_1:
976
28.1k
        if ('D' == c ||              // $SD, Depth-sounder
977
22.7k
            'N' == c ||              // $SN, to $SNRSTAT
978
20.6k
            'T' == c) {              // $ST, to $STI
979
            // leader accepted
980
20.6k
            lexer->state = NMEA_LEADER_END;
981
20.6k
        } else {
982
7.50k
            return character_pushback(lexer, GROUND_STATE);
983
7.50k
        }
984
20.6k
        break;
985
20.6k
    case TRANSDUCER_LEAD_1:
986
2.16k
        if ('X' == c) {           // $YX, Transducer leader accepted
987
690
            lexer->state = NMEA_LEADER_END;
988
1.47k
        } else {
989
1.47k
            return character_pushback(lexer, GROUND_STATE);
990
1.47k
        }
991
690
        break;
992
5.10k
    case BEIDOU_LEAD_1:
993
5.10k
        if ('D' == c) {           // $BD, Beidou leader accepted
994
2.86k
            lexer->state = NMEA_LEADER_END;
995
2.86k
        } else {
996
2.24k
            return character_pushback(lexer, GROUND_STATE);
997
2.24k
        }
998
2.86k
        break;
999
2.86k
    case QZSS_LEAD_1:
1000
2.60k
        if ('Z' == c) {           // $QZ, QZSS leader accepted
1001
575
            lexer->state = NMEA_LEADER_END;
1002
2.03k
        } else {
1003
2.03k
            return character_pushback(lexer, GROUND_STATE);
1004
2.03k
        }
1005
575
        break;
1006
575
#ifdef TRIPMATE_ENABLE
1007
238k
    case ASTRAL_1:
1008
238k
        if ('S' == c) {       // AS
1009
15.6k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1010
855
                lexer->state = RTCM2_SYNC_STATE;
1011
855
                break;
1012
14.8k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1013
194
                lexer->state = RTCM2_RECOGNIZED;
1014
194
                break;
1015
194
            }
1016
14.6k
            lexer->state = ASTRAL_2;
1017
14.6k
        } else
1018
223k
            (void)character_pushback(lexer, GROUND_STATE);
1019
237k
        break;
1020
237k
    case ASTRAL_2:
1021
14.6k
        if ('T' == c) {        // AST
1022
6.36k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1023
619
                lexer->state = RTCM2_SYNC_STATE;
1024
619
                break;
1025
5.74k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1026
0
                lexer->state = RTCM2_RECOGNIZED;
1027
0
                break;
1028
0
            }
1029
5.74k
            lexer->state = ASTRAL_3;
1030
8.23k
        } else {
1031
8.23k
            (void)character_pushback(lexer, GROUND_STATE);
1032
8.23k
        }
1033
13.9k
        break;
1034
13.9k
    case ASTRAL_3:
1035
5.74k
        if ('R' == c) {      // ASTR
1036
4.21k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1037
806
                lexer->state = RTCM2_SYNC_STATE;
1038
806
                break;
1039
3.41k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1040
0
                lexer->state = RTCM2_RECOGNIZED;
1041
0
                break;
1042
0
            }
1043
3.41k
            lexer->state = ASTRAL_5;
1044
3.41k
        } else {
1045
1.52k
            (void)character_pushback(lexer, GROUND_STATE);
1046
1.52k
        }
1047
4.93k
        break;
1048
4.93k
    case ASTRAL_4:
1049
0
        if ('A' == c) {    // ASTRA
1050
0
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1051
0
                lexer->state = RTCM2_SYNC_STATE;
1052
0
                break;
1053
0
            } else if (ISGPS_MESSAGE == isgpsstat) {
1054
0
                lexer->state = RTCM2_RECOGNIZED;
1055
0
                break;
1056
0
            }
1057
0
            lexer->state = ASTRAL_2;
1058
0
        } else {
1059
0
            (void)character_pushback(lexer, GROUND_STATE);
1060
0
        }
1061
0
        break;
1062
3.40k
    case ASTRAL_5:
1063
3.40k
        if ('L' == c) {       // ASTRAL
1064
1.14k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1065
230
                lexer->state = RTCM2_SYNC_STATE;
1066
230
                break;
1067
913
            } else if (ISGPS_MESSAGE == isgpsstat) {
1068
0
                lexer->state = RTCM2_RECOGNIZED;
1069
0
                break;
1070
0
            }
1071
913
            lexer->state = NMEA_RECOGNIZED;
1072
2.26k
        } else {
1073
2.26k
            (void)character_pushback(lexer, GROUND_STATE);
1074
2.26k
        }
1075
3.17k
        break;
1076
3.17k
#endif  // TRIPMATE_ENABLE
1077
3.17k
#ifdef EARTHMATE_ENABLE
1078
104k
    case EARTHA_1:
1079
104k
        if ('A' == c) {     // EA
1080
13.8k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1081
548
                lexer->state = RTCM2_SYNC_STATE;
1082
548
                break;
1083
13.3k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1084
354
                lexer->state = RTCM2_RECOGNIZED;
1085
354
                break;
1086
354
            }
1087
12.9k
            lexer->state = EARTHA_2;
1088
91.1k
        } else {
1089
91.1k
            (void)character_pushback(lexer, GROUND_STATE);
1090
91.1k
        }
1091
104k
        break;
1092
104k
    case EARTHA_2:
1093
12.9k
        if ('R' == c) {     // EAR
1094
7.43k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1095
737
                lexer->state = RTCM2_SYNC_STATE;
1096
737
                break;
1097
6.69k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1098
0
                lexer->state = RTCM2_RECOGNIZED;
1099
0
                break;
1100
0
            }
1101
6.69k
            lexer->state = EARTHA_3;
1102
6.69k
        } else {
1103
5.54k
            (void)character_pushback(lexer, GROUND_STATE);
1104
5.54k
        }
1105
12.2k
        break;
1106
12.2k
    case EARTHA_3:
1107
6.69k
        if ('T' == c) {       // EART
1108
5.05k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1109
649
                lexer->state = RTCM2_SYNC_STATE;
1110
649
                break;
1111
4.40k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1112
0
                lexer->state = RTCM2_RECOGNIZED;
1113
0
                break;
1114
0
            }
1115
4.40k
            lexer->state = EARTHA_4;
1116
4.40k
        } else {
1117
1.63k
            (void)character_pushback(lexer, GROUND_STATE);
1118
1.63k
        }
1119
6.04k
        break;
1120
6.04k
    case EARTHA_4:
1121
4.40k
        if ('H' == c) {        // EARTH
1122
3.36k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1123
271
                lexer->state = RTCM2_SYNC_STATE;
1124
271
                break;
1125
3.09k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1126
0
                lexer->state = RTCM2_RECOGNIZED;
1127
0
                break;
1128
0
            }
1129
3.09k
            lexer->state = EARTHA_5;
1130
3.09k
        } else {
1131
1.04k
            (void)character_pushback(lexer, GROUND_STATE);
1132
1.04k
        }
1133
4.13k
        break;
1134
4.13k
    case EARTHA_5:
1135
3.09k
        if ('A' == c) {     // EARTHA
1136
1.92k
            if (ISGPS_SYNC == (isgpsstat = rtcm2_decode(lexer, c))) {
1137
0
                lexer->state = RTCM2_SYNC_STATE;
1138
0
                break;
1139
1.92k
            } else if (ISGPS_MESSAGE == isgpsstat) {
1140
0
                lexer->state = RTCM2_RECOGNIZED;
1141
0
                break;
1142
0
            }
1143
1.92k
            lexer->state = NMEA_RECOGNIZED;
1144
1.92k
        } else {
1145
1.16k
            (void)character_pushback(lexer, GROUND_STATE);
1146
1.16k
        }
1147
3.09k
        break;
1148
3.09k
#endif  // EARTHMATE_ENABLE
1149
24.2k
    case NMEA_LEAD_A:
1150
24.2k
        if ('c' == c) {                // $Ac
1151
1.58k
            lexer->state = SIRF_ACK_LEAD_2;
1152
22.6k
        } else if ('I' == c) {         // $AI, Mobile Class A or B AIS Station
1153
15.5k
            lexer->state = AIS_LEAD_2;
1154
15.5k
        } else if ('P' == c) {         // $AP, auto pilot
1155
2.45k
            lexer->state = NMEA_LEADER_END;
1156
4.68k
        } else {
1157
4.68k
            return character_pushback(lexer, GROUND_STATE);
1158
4.68k
        }
1159
19.5k
        break;
1160
19.5k
    case SIRF_ACK_LEAD_2:
1161
1.58k
        if ('k' == c) {                // $Ack
1162
703
            lexer->state = NMEA_LEADER_END;
1163
880
        } else {
1164
880
            return character_pushback(lexer, GROUND_STATE);
1165
880
        }
1166
703
        break;
1167
703
#if defined(SIRF_ENABLE) || defined(SKYTRAQ_ENABLE)
1168
1.31M
    case SIRF_LEADER_1:
1169
1.31M
# ifdef SKYTRAQ_ENABLE
1170
        // Skytraq leads with 0xA0,0xA1
1171
1.31M
        if (0xa1 == c) {
1172
96.2k
            lexer->state = SKY_LEADER_2;
1173
96.2k
            break;
1174
96.2k
        }
1175
1.21M
# endif // SKYTRAQ_ENABLE
1176
1.21M
# ifdef SIRF_ENABLE
1177
        // SIRF leads with 0xA0,0xA2
1178
1.21M
        if (0xa2 == c) {
1179
31.8k
            lexer->state = SIRF_LEADER_2;
1180
31.8k
            break;
1181
31.8k
        }
1182
1.18M
# endif // SIRF_ENABLE
1183
1.18M
        return character_pushback(lexer, GROUND_STATE);
1184
0
        break;
1185
0
#endif  // SIRF_ENABLE || SKYTRAQ_ENABLE
1186
0
#ifdef SIRF_ENABLE
1187
31.8k
    case SIRF_LEADER_2:
1188
        // first part of length, MSB
1189
31.8k
        lexer->length = (c & 0x7f) << 8;
1190
31.8k
        if (lexer->length > MAX_PACKET_LENGTH) {
1191
2.80k
            lexer->length = 0;
1192
2.80k
            return character_pushback(lexer, GROUND_STATE);
1193
2.80k
        } // else
1194
29.0k
        lexer->state = SIRF_LENGTH_1;
1195
29.0k
        break;
1196
28.7k
    case SIRF_LENGTH_1:
1197
        // second part of length
1198
28.7k
        lexer->length += c + 2;
1199
28.7k
        if (lexer->length > MAX_PACKET_LENGTH) {
1200
1.20k
            lexer->length = 0;
1201
1.20k
            return character_pushback(lexer, GROUND_STATE);
1202
1.20k
        } // else
1203
27.5k
        lexer->state = SIRF_PAYLOAD;
1204
27.5k
        break;
1205
633k
    case SIRF_PAYLOAD:
1206
633k
        if (0 == --lexer->length) {
1207
27.3k
            lexer->state = SIRF_DELIVERED;
1208
27.3k
        }
1209
633k
        break;
1210
27.3k
    case SIRF_DELIVERED:
1211
27.3k
        if (0xb0 == c) {     // latin1 degree sign
1212
16.5k
            lexer->state = SIRF_TRAILER_1;
1213
16.5k
        } else {
1214
10.7k
            return character_pushback(lexer, GROUND_STATE);
1215
10.7k
        }
1216
16.5k
        break;
1217
16.5k
    case SIRF_TRAILER_1:
1218
16.5k
        if (0xb3 == c) {     // latin1 superscript 3
1219
15.2k
            lexer->state = SIRF_RECOGNIZED;
1220
15.2k
        } else {
1221
1.26k
            return character_pushback(lexer, GROUND_STATE);
1222
1.26k
        }
1223
15.2k
        break;
1224
15.2k
    case SIRF_RECOGNIZED:
1225
12.5k
        if (0xa0 == c) {     // latin1 no break space
1226
3.37k
            lexer->state = SIRF_LEADER_1;
1227
9.22k
        } else {
1228
9.22k
            return character_pushback(lexer, GROUND_STATE);
1229
9.22k
        }
1230
3.37k
        break;
1231
3.37k
#endif  // SIRF_ENABLE
1232
3.37k
#ifdef SKYTRAQ_ENABLE
1233
96.2k
    case SKY_LEADER_2:
1234
        // MSB of length is first
1235
96.2k
        lexer->length = (size_t)(c << 8);
1236
96.2k
        lexer->state = SKY_LENGTH_1;
1237
96.2k
        break;
1238
85.1k
    case SKY_LENGTH_1:
1239
        // Skytraq length can be any 16 bit number, except 0
1240
85.1k
        lexer->length += c;
1241
85.1k
        if (0 == lexer->length) {
1242
1.28k
            return character_pushback(lexer, GROUND_STATE);
1243
1.28k
        }
1244
83.9k
        if (MAX_PACKET_LENGTH < lexer->length) {
1245
0
            lexer->length = 0;
1246
0
            return character_pushback(lexer, GROUND_STATE);
1247
0
        }
1248
83.9k
        lexer->state = SKY_PAYLOAD;
1249
83.9k
        break;
1250
1.65M
    case SKY_PAYLOAD:
1251
1.65M
        if (0 == --lexer->length) {
1252
83.6k
            lexer->state = SKY_DELIVERED;
1253
83.6k
        }
1254
1.65M
        break;
1255
83.5k
    case SKY_DELIVERED:
1256
83.5k
        {
1257
83.5k
            char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
1258
83.5k
            unsigned char csum = 0;
1259
1260
83.5k
            GPSD_LOG(LOG_RAW, &lexer->errout,
1261
83.5k
                     "Skytraq = %s\n",
1262
83.5k
                     gpsd_packetdump(scratchbuf,  sizeof(scratchbuf),
1263
83.5k
                         lexer->inbuffer,
1264
83.5k
                         lexer->inbufptr - (unsigned char *)lexer->inbuffer));
1265
83.5k
            for (n = 4;
1266
33.3M
                 (unsigned char *)(lexer->inbuffer + n) < lexer->inbufptr - 1;
1267
33.2M
                 n++) {
1268
33.2M
                csum ^= lexer->inbuffer[n];
1269
33.2M
            }
1270
83.5k
            if (csum != c) {
1271
51.4k
                GPSD_LOG(LOG_PROG, &lexer->errout,
1272
51.4k
                         "Skytraq bad checksum 0x%hhx, expecting 0x%x\n",
1273
51.4k
                         csum, c);
1274
51.4k
                lexer->state = GROUND_STATE;
1275
51.4k
                break;
1276
51.4k
            }
1277
83.5k
        }
1278
32.1k
        lexer->state = SKY_CSUM;
1279
32.1k
        break;
1280
32.1k
    case SKY_CSUM:
1281
32.1k
        if ('\r' != c) {
1282
12.7k
            return character_pushback(lexer, GROUND_STATE);
1283
12.7k
        }
1284
19.4k
        lexer->state = SKY_TRAILER_1;
1285
19.4k
        break;
1286
19.4k
    case SKY_TRAILER_1:
1287
19.4k
        if ('\n' != c) {
1288
1.34k
            return character_pushback(lexer, GROUND_STATE);
1289
1.34k
        }
1290
18.0k
        lexer->state = SKY_RECOGNIZED;
1291
18.0k
        break;
1292
17.4k
    case SKY_RECOGNIZED:
1293
17.4k
        if (0xa0 != c) {     // non break space
1294
13.5k
            return character_pushback(lexer, GROUND_STATE);
1295
13.5k
        }
1296
3.92k
        lexer->state = SIRF_LEADER_1;
1297
3.92k
        break;
1298
0
#endif  // SKYTRAQ
1299
0
    case SPARTN_PRE_1:
1300
        // message type, 1 bit of length
1301
0
        lexer->length = c & 1;
1302
0
        lexer->state = SPARTN_PRE_2;
1303
0
        break;
1304
0
    case SPARTN_PRE_2:
1305
        // 8 bits of length
1306
0
        lexer->length = (lexer->length << 8) + (c & 0xff);
1307
0
        lexer->state = SPARTN_PRE_3;
1308
0
        break;
1309
0
    case SPARTN_PRE_3:
1310
        // 1 bit of length, 1 bit of eaf, 2 bits CRC type, 4 bits frame CRC
1311
0
        lexer->length = (lexer->length << 1) + ((c >> 7) & 1);
1312
0
        lexer->state = SPARTN_PAYDESC_1;
1313
0
        break;
1314
0
    case SPARTN_PAYDESC_1:
1315
        // 4 bits subtype, 1 bit time tag type,  3 bits time tag
1316
0
        lexer->state = SPARTN_PAYDESC_2;
1317
0
        GPSD_LOG(LOG_RAW, &lexer->errout,
1318
0
                 "SPARTN: PD1 length %zu eaf %u subtype %u  "
1319
0
                  "timetagtype %u c[4] x%x\n",
1320
0
                  lexer->length, (lexer->inbuffer[3] >> 6) & 1,
1321
0
                  (c >> 4) & 0x0f, (c >> 3) & 1,lexer->inbuffer[3]);
1322
0
        break;
1323
0
    case SPARTN_PAYDESC_2:
1324
        // 8 bits timetag
1325
0
        lexer->state = SPARTN_PAYDESC_3;
1326
0
        break;
1327
0
    case SPARTN_PAYDESC_3:
1328
        // 5 bits timetag 3 bits of (tt2 or solution)
1329
0
        if (0x08 == (lexer->inbuffer[4] & 0x08)) {
1330
            // eaf 1 means 2 extra payload description bytes (timetag2)
1331
0
            lexer->state = SPARTN_PAYDESC_4;
1332
0
        } else {
1333
0
            lexer->state = SPARTN_PAYDESC_6;
1334
0
        }
1335
0
        break;
1336
0
    case SPARTN_PAYDESC_4:
1337
        // 8 bits timetag2
1338
0
        lexer->state = SPARTN_PAYDESC_5;
1339
0
        break;
1340
0
    case SPARTN_PAYDESC_5:
1341
        // 5 bits timetag2 3 bits of solution proc ID
1342
0
        lexer->state = SPARTN_PAYDESC_6;
1343
0
        break;
1344
0
    case SPARTN_PAYDESC_6:
1345
        //   4 bits solution ID, 4 bits Solution Proc ID
1346
0
        if (0x40 == (lexer->inbuffer[3] & 0x40)) {
1347
            // eaf 1 means 2 extra payload description bytes
1348
0
            lexer->state = SPARTN_PAYDESC_7;
1349
0
        } else {
1350
0
            lexer->state = SPARTN_PAYLOAD;
1351
0
        }
1352
        // add CRC length, 1, 2, 3, or 4 bytes
1353
0
        lexer->length += ((lexer->inbuffer[3] >> 4) & 3) + 1;
1354
0
        GPSD_LOG(LOG_RAW, &lexer->errout,
1355
0
                 "SPARTN: PD6 length %zu eaf %u timetagtype %u "
1356
0
                  "crct %u\n",
1357
0
                  lexer->length, (lexer->inbuffer[3] >> 6) & 1,
1358
0
                  (lexer->inbuffer[4] >> 3) & 1,
1359
0
                  (lexer->inbuffer[3] >> 4) & 3);
1360
0
        break;
1361
0
    case SPARTN_PAYDESC_7:
1362
        // 4 bits Enc ID, 4 bits Enc Seq Num
1363
0
        lexer->state = SPARTN_PAYDESC_8;
1364
0
        break;
1365
0
    case SPARTN_PAYDESC_8:
1366
        // 2 bit Enc Seq Num, 1 bit Auth Ind, 3 Embed Auth Len
1367
0
        lexer->state = SPARTN_PAYLOAD;
1368
0
        lexer->length += spartn_auth_len(c & 3);
1369
0
        GPSD_LOG(LOG_RAW, &lexer->errout,
1370
0
                 "SPARTN: PD8 x%02x length %zu eaf %u timetagtype %u "
1371
0
                  "eal %u/%u\n",
1372
0
                  c, lexer->length, (lexer->inbuffer[3] >> 6) & 1,
1373
0
                  (lexer->inbuffer[4] >> 3) & 1,
1374
0
                  c & 3, spartn_auth_len(c &  3));
1375
0
        break;
1376
0
    case SPARTN_PAYLOAD:
1377
0
        if (0 == --lexer->length) {
1378
            // Done with payload, encryption and crc
1379
0
            lexer->state = SPARTN_RECOGNIZED;
1380
0
        }
1381
0
        GPSD_LOG(LOG_RAW, &lexer->errout,
1382
0
                 "SPARTN: PAY x%02x length4 %zu eaf %u timetagtype %u\n",
1383
0
                  c, lexer->length, (lexer->inbuffer[3] >> 6) & 1,
1384
0
                  (lexer->inbuffer[4] >> 3) & 1);
1385
0
        break;
1386
1387
0
#ifdef SUPERSTAR2_ENABLE
1388
305k
    case SUPERSTAR2_LEADER:
1389
305k
        ctmp = c;          // seems a dodgy way to keep state...
1390
305k
        lexer->state = SUPERSTAR2_ID1;
1391
305k
        break;
1392
305k
    case SUPERSTAR2_ID1:
1393
305k
        if ((ctmp ^ 0xff) == c) {
1394
9.77k
            lexer->state = SUPERSTAR2_ID2;
1395
295k
        } else {
1396
295k
            return character_pushback(lexer, GROUND_STATE);
1397
295k
        }
1398
9.77k
        break;
1399
9.77k
    case SUPERSTAR2_ID2:
1400
9.75k
        lexer->length = (size_t) c;  // how many data bytes follow this byte
1401
9.75k
        if (lexer->length) {
1402
3.85k
            lexer->state = SUPERSTAR2_PAYLOAD;
1403
5.89k
        } else {
1404
5.89k
            lexer->state = SUPERSTAR2_CKSUM1;   // no data, jump to checksum
1405
5.89k
        }
1406
9.75k
        break;
1407
105k
    case SUPERSTAR2_PAYLOAD:
1408
105k
        if (0 == --lexer->length) {
1409
            // Done with payload
1410
3.72k
            lexer->state = SUPERSTAR2_CKSUM1;
1411
3.72k
        }
1412
105k
        break;
1413
9.61k
    case SUPERSTAR2_CKSUM1:
1414
9.61k
        lexer->state = SUPERSTAR2_CKSUM2;
1415
9.61k
        break;
1416
9.60k
    case SUPERSTAR2_CKSUM2:
1417
        // checksum not checked here?
1418
9.60k
        lexer->state = SUPERSTAR2_RECOGNIZED;
1419
9.60k
        break;
1420
3.97k
    case SUPERSTAR2_RECOGNIZED:
1421
3.97k
        if (SOH == c) {
1422
1.35k
            lexer->state = SUPERSTAR2_LEADER;
1423
2.61k
        } else {
1424
2.61k
            return character_pushback(lexer, GROUND_STATE);
1425
2.61k
        }
1426
1.35k
        break;
1427
1.35k
#endif  // SUPERSTAR2_ENABLE
1428
1.35k
#ifdef ONCORE_ENABLE
1429
82.8M
    case ONCORE_AT2:
1430
82.8M
        if (isupper(c)) {
1431
482k
            lexer->length = (size_t)c;
1432
482k
            lexer->state = ONCORE_ID1;
1433
82.3M
        } else {
1434
82.3M
            return character_pushback(lexer, GROUND_STATE);
1435
82.3M
        }
1436
482k
        break;
1437
858k
    case ONCORE_ID1:
1438
858k
        if (!isalpha(c)) {
1439
197k
            return character_pushback(lexer, GROUND_STATE);
1440
197k
        }
1441
660k
        lexer->length =
1442
660k
            oncore_payload_cksum_length((unsigned char)lexer->length, c);
1443
660k
        if (0 != lexer->length) {
1444
284k
            lexer->state = ONCORE_PAYLOAD;
1445
284k
        }
1446
        // else?
1447
660k
        break;
1448
1.73M
    case ONCORE_PAYLOAD:
1449
1.73M
        if (0 == --lexer->length) {
1450
284k
            lexer->state = ONCORE_CHECKSUM;
1451
284k
        }
1452
1.73M
        break;
1453
284k
    case ONCORE_CHECKSUM:
1454
284k
        if ('\r' != c) {
1455
274k
            return character_pushback(lexer, GROUND_STATE);
1456
274k
        }
1457
9.63k
        lexer->state = ONCORE_CR;
1458
9.63k
        break;
1459
9.63k
    case ONCORE_CR:
1460
9.63k
        if ('\n' == c) {
1461
8.62k
            lexer->state = ONCORE_RECOGNIZED;
1462
8.62k
        } else {
1463
1.01k
            lexer->state = ONCORE_PAYLOAD;
1464
1.01k
        }
1465
9.63k
        break;
1466
7.18k
    case ONCORE_RECOGNIZED:
1467
7.18k
        if ('@' == c) {
1468
1.87k
            lexer->state = AT1_LEADER;
1469
5.30k
        } else {
1470
5.30k
            return character_pushback(lexer, GROUND_STATE);
1471
5.30k
        }
1472
1.87k
        break;
1473
1.87k
#endif  // ONCORE_ENABLE
1474
1.87k
#if defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(GARMIN_ENABLE)
1475
384k
    case DLE_LEADER:
1476
384k
#ifdef EVERMORE_ENABLE
1477
384k
        if (STX == c) {        // DLE (0x10), STX (0x01)
1478
28.6k
            lexer->state = EVERMORE_LEADER_2;
1479
28.6k
            break;
1480
28.6k
        }
1481
355k
#endif  // EVERMORE_ENABLE
1482
355k
#if defined(TSIP_ENABLE) || defined(GARMIN_ENABLE) || defined(NAVCOM_ENABLE)
1483
        // garmin is special case of TSIP
1484
        // check last because there's no checksum
1485
355k
#if defined(TSIP_ENABLE)
1486
355k
        if (0x13 <= c) {       // DLE (0x10), DC3
1487
206k
            lexer->length = TSIP_MAX_PACKET;
1488
206k
            lexer->state = TSIP_PAYLOAD;
1489
206k
            break;
1490
206k
        }
1491
149k
#endif  // TSIP_ENABLE
1492
149k
        if (DLE == c) {        // DLE (0x10), DLE (0x10)
1493
65.6k
            lexer->state = GROUND_STATE;
1494
65.6k
            break;
1495
65.6k
        }
1496
        // give up
1497
84.2k
        lexer->state = GROUND_STATE;
1498
84.2k
        break;
1499
0
#endif  // TSIP_ENABLE
1500
0
#ifdef NAVCOM_ENABLE
1501
1.69M
    case NAVCOM_LEADER_1:
1502
1.69M
        if (0x99 == c) {        // latin1 TM (0x99)
1503
99.1k
            lexer->state = NAVCOM_LEADER_2;
1504
1.59M
        } else {
1505
1.59M
            return character_pushback(lexer, GROUND_STATE);
1506
1.59M
        }
1507
99.1k
        break;
1508
99.1k
    case NAVCOM_LEADER_2:
1509
99.1k
        if ('f' == c) {        // (TM), f
1510
89.7k
            lexer->state = NAVCOM_LEADER_3;
1511
89.7k
        } else {
1512
9.46k
            return character_pushback(lexer, GROUND_STATE);
1513
9.46k
        }
1514
89.7k
        break;
1515
89.7k
    case NAVCOM_LEADER_3:
1516
        // command ID
1517
89.7k
        lexer->state = NAVCOM_ID;
1518
89.7k
        break;
1519
89.7k
    case NAVCOM_ID:
1520
        // Length LSB
1521
89.7k
        lexer->length = c;
1522
89.7k
        lexer->state = NAVCOM_LENGTH_1;
1523
89.7k
        break;
1524
89.7k
    case NAVCOM_LENGTH_1:
1525
        /* Length USB.  Navcom allows payload length up to 32767 - 4
1526
         * Navcom length includes command ID, length bytes. and checksum.
1527
         * More than just the payload length.
1528
         * Minimum 4 bytes */
1529
89.7k
        lexer->length += (c << 8);
1530
89.7k
        if (4 >lexer->length ) {
1531
            // too short
1532
864
            return character_pushback(lexer, GROUND_STATE);
1533
864
        }
1534
        // don't count ID, length and checksum  in payload length
1535
88.8k
        lexer->length -= 4;
1536
88.8k
        if (MAX_PACKET_LENGTH < lexer->length) {
1537
18.4k
            lexer->length = 0;
1538
18.4k
            return character_pushback(lexer, GROUND_STATE);
1539
18.4k
        }  // else
1540
70.3k
        lexer->state = NAVCOM_LENGTH_2;
1541
70.3k
        break;
1542
895k
    case NAVCOM_LENGTH_2:
1543
895k
        if (0 == --lexer->length) {
1544
70.0k
            lexer->state = NAVCOM_PAYLOAD;
1545
70.0k
        }
1546
895k
        break;
1547
70.0k
    case NAVCOM_PAYLOAD:
1548
70.0k
        {
1549
70.0k
            unsigned char csum = lexer->inbuffer[3];
1550
70.0k
            for (n = 4;
1551
74.4M
                 (unsigned char *)(lexer->inbuffer + n) < lexer->inbufptr - 1;
1552
74.4M
                 n++)
1553
74.4M
                csum ^= lexer->inbuffer[n];
1554
70.0k
            if (csum != c) {
1555
51.9k
                GPSD_LOG(LOG_PROG, &lexer->errout,
1556
51.9k
                         "Navcom packet type 0x%hhx bad checksum 0x%hhx, "
1557
51.9k
                         "expecting 0x%x\n",
1558
51.9k
                         lexer->inbuffer[3], csum, c);
1559
51.9k
                lexer->state = GROUND_STATE;
1560
51.9k
                break;
1561
51.9k
            }
1562
70.0k
        }
1563
18.0k
        lexer->state = NAVCOM_CSUM;
1564
18.0k
        break;
1565
17.9k
    case NAVCOM_CSUM:
1566
17.9k
        if (ETX == c) {     // ETX (0x03)
1567
9.48k
            lexer->state = NAVCOM_RECOGNIZED;
1568
9.48k
        } else {
1569
8.51k
            return character_pushback(lexer, GROUND_STATE);
1570
8.51k
        }
1571
9.48k
        break;
1572
9.48k
    case NAVCOM_RECOGNIZED:
1573
9.43k
        if (STX == c) {     // STX (0x02)
1574
913
            lexer->state = NAVCOM_LEADER_1;
1575
8.52k
        } else {
1576
8.52k
            return character_pushback(lexer, GROUND_STATE);
1577
8.52k
        }
1578
913
        break;
1579
913
#endif  // NAVCOM_ENABLE
1580
913
#endif  // TSIP_ENABLE || EVERMORE_ENABLE || GARMIN_ENABLE
1581
70.7M
    case RTCM3_LEADER_1:
1582
        // high 6 bits must be zero, low 2 bits are MSB of a 10-bit length
1583
70.7M
        if (0 == (c & 0xFC)) {
1584
11.3k
            lexer->length = (size_t)c << 8;
1585
11.3k
            lexer->state = RTCM3_LEADER_2;
1586
70.7M
        } else {
1587
70.7M
            GPSD_LOG(LOG_IO, &lexer->errout,
1588
70.7M
                     "RTCM3 must be zero bits aren't: %u\n", c & 0xFC);
1589
70.7M
            return character_pushback(lexer, GROUND_STATE);
1590
70.7M
        }
1591
11.3k
        break;
1592
11.3k
    case RTCM3_LEADER_2:
1593
        // third byte is the low 8 bits of the RTCM3 packet length
1594
11.2k
        lexer->length |= c;
1595
11.2k
        lexer->length += 3;     // to get the three checksum bytes
1596
11.2k
        lexer->state = RTCM3_PAYLOAD;
1597
11.2k
        break;
1598
207k
    case RTCM3_PAYLOAD:
1599
207k
        if (0 == --lexer->length) {
1600
11.1k
            lexer->state = RTCM3_RECOGNIZED;
1601
11.1k
        }
1602
207k
        break;
1603
0
#ifdef ZODIAC_ENABLE
1604
0
    case ZODIAC_EXPECTED:
1605
0
        FALLTHROUGH
1606
1.55k
    case ZODIAC_RECOGNIZED:
1607
1.55k
        if (0xff == c) {         // y with diaeresis
1608
803
            lexer->state = ZODIAC_LEADER_1;
1609
803
        } else {
1610
748
            return character_pushback(lexer, GROUND_STATE);
1611
748
        }
1612
803
        break;
1613
810k
    case ZODIAC_LEADER_1:
1614
810k
        if (0x81 == c) {         // latin1 non-printing
1615
48.4k
            lexer->state = ZODIAC_LEADER_2;
1616
762k
        } else {
1617
762k
            (void)character_pushback(lexer, GROUND_STATE);
1618
762k
        }
1619
810k
        break;
1620
48.4k
    case ZODIAC_LEADER_2:
1621
48.4k
        lexer->state = ZODIAC_ID_1;
1622
48.4k
        break;
1623
48.4k
    case ZODIAC_ID_1:
1624
48.4k
        lexer->state = ZODIAC_ID_2;
1625
48.4k
        break;
1626
48.4k
    case ZODIAC_ID_2:
1627
48.4k
        lexer->length = (size_t)c;
1628
48.4k
        lexer->state = ZODIAC_LENGTH_1;
1629
48.4k
        break;
1630
48.3k
    case ZODIAC_LENGTH_1:
1631
48.3k
        lexer->length += (c << 8);
1632
48.3k
        lexer->state = ZODIAC_LENGTH_2;
1633
48.3k
        break;
1634
18.4k
    case ZODIAC_LENGTH_2:
1635
18.4k
        lexer->state = ZODIAC_FLAGS_1;
1636
18.4k
        break;
1637
18.4k
    case ZODIAC_FLAGS_1:
1638
18.4k
        lexer->state = ZODIAC_FLAGS_2;
1639
18.4k
        break;
1640
18.4k
    case ZODIAC_FLAGS_2:
1641
18.4k
        lexer->state = ZODIAC_HSUM_1;
1642
18.4k
        break;
1643
18.4k
    case ZODIAC_HSUM_1:
1644
18.4k
        {
1645
18.4k
            short sum = getzword(0) + getzword(1) + getzword(2) + getzword(3);
1646
18.4k
            sum *= -1;
1647
18.4k
            if (sum != getzword(4)) {
1648
15.1k
                GPSD_LOG(LOG_PROG, &lexer->errout,
1649
15.1k
                         "Zodiac Header checksum 0x%x expecting 0x%x\n",
1650
15.1k
                         sum, getzword(4));
1651
15.1k
                lexer->state = GROUND_STATE;
1652
15.1k
                break;
1653
15.1k
            }
1654
18.4k
        }
1655
3.31k
        GPSD_LOG(LOG_RAW1, &lexer->errout,
1656
3.31k
                 "Zodiac header id=%u len=%u flags=%x\n",
1657
3.31k
                 getzuword(1), getzuword(2), getzuword(3));
1658
3.31k
        if (0 == lexer->length) {
1659
1.75k
            lexer->state = ZODIAC_RECOGNIZED;
1660
1.75k
            break;
1661
1.75k
        }
1662
1.55k
        lexer->length *= 2;     // word count to byte count
1663
1.55k
        lexer->length += 2;     // checksum
1664
        // 10 bytes is the length of the Zodiac header
1665
        // no idea what Zodiac max length really is
1666
1.55k
        if ((MAX_PACKET_LENGTH - 10) < lexer->length) {
1667
780
            lexer->length = 0;
1668
780
            return character_pushback(lexer, GROUND_STATE);
1669
780
        }  // else
1670
774
        lexer->state = ZODIAC_PAYLOAD;
1671
774
        break;
1672
8.51k
    case ZODIAC_PAYLOAD:
1673
8.51k
        if (0 == --lexer->length) {
1674
707
            lexer->state = ZODIAC_RECOGNIZED;
1675
707
        }
1676
8.51k
        break;
1677
0
#endif  // ZODIAC_ENABLE
1678
1.42M
    case UBX_LEADER_1:
1679
1.42M
        if ('b' == c) {      // micro, b
1680
51.2k
            lexer->state = UBX_LEADER_2;
1681
1.37M
        } else {
1682
1.37M
            return character_pushback(lexer, GROUND_STATE);
1683
1.37M
        }
1684
51.2k
        break;
1685
51.2k
    case UBX_LEADER_2:
1686
51.2k
        lexer->state = UBX_CLASS_ID;
1687
51.2k
        break;
1688
51.2k
    case UBX_CLASS_ID:
1689
51.2k
        lexer->state = UBX_MESSAGE_ID;
1690
51.2k
        break;
1691
51.2k
    case UBX_MESSAGE_ID:
1692
51.2k
        lexer->length = (size_t)c;
1693
51.2k
        lexer->state = UBX_LENGTH_1;
1694
51.2k
        break;
1695
51.1k
    case UBX_LENGTH_1:
1696
51.1k
        lexer->length += (c << 8);
1697
51.1k
        if (0 == lexer->length) {
1698
            // no payload
1699
10.4k
            lexer->state = UBX_CHECKSUM_A;
1700
40.6k
        } else if (MAX_PACKET_LENGTH >= lexer->length) {
1701
            // normal size payload
1702
18.4k
            lexer->state = UBX_LENGTH_2;
1703
22.2k
        } else {
1704
            // bad length
1705
22.2k
            lexer->length = 0;
1706
22.2k
            return character_pushback(lexer, GROUND_STATE);
1707
22.2k
        }
1708
28.8k
        break;
1709
28.8k
    case UBX_LENGTH_2:
1710
17.6k
        lexer->state = UBX_PAYLOAD;
1711
17.6k
        break;
1712
1.55M
    case UBX_PAYLOAD:
1713
1.55M
        if (0 == --lexer->length) {
1714
17.3k
            lexer->state = UBX_CHECKSUM_A;
1715
17.3k
        }
1716
        // else stay in payload state
1717
1.55M
        break;
1718
27.8k
    case UBX_CHECKSUM_A:
1719
27.8k
        lexer->state = UBX_RECOGNIZED;
1720
27.8k
        break;
1721
17.4k
    case UBX_RECOGNIZED:
1722
17.4k
        if (MICRO == c) {       // latin1 micro (0xb5)
1723
2.61k
            lexer->state = UBX_LEADER_1;
1724
14.7k
        } else if ('$' == c) {  // LEA-5H can/will output NMEA/UBX back to back
1725
981
            lexer->state = NMEA_DOLLAR;
1726
13.8k
        } else if ('{' == c) {
1727
            // codacy thinks this can never happen
1728
394
            return character_pushback(lexer, JSON_LEADER);
1729
13.4k
        } else {
1730
13.4k
            return character_pushback(lexer, GROUND_STATE);
1731
13.4k
        }
1732
3.59k
        break;
1733
1734
    // start ALLYSTAR
1735
362k
    case ALLY_LEADER_1:
1736
362k
        if (0xd9 == c) {      // latin capital letter U with grave
1737
            // got 2nd, of 2, bytes of leader
1738
17.2k
            lexer->state = ALLY_LEADER_2;
1739
344k
        } else {
1740
344k
            return character_pushback(lexer, GROUND_STATE);
1741
344k
        }
1742
17.2k
        break;
1743
17.2k
    case ALLY_LEADER_2:
1744
        // got 1 byte Class ID
1745
17.1k
        lexer->state = ALLY_CLASS_ID;
1746
17.1k
        break;
1747
17.1k
    case ALLY_CLASS_ID:
1748
        // got 1 byte Message ID
1749
17.1k
        lexer->state = ALLY_MESSAGE_ID;
1750
17.1k
        break;
1751
17.1k
    case ALLY_MESSAGE_ID:
1752
        // got 1st, of 2, bytes of length
1753
17.1k
        lexer->length = (size_t)c;
1754
17.1k
        lexer->state = ALLY_LENGTH_1;
1755
17.1k
        break;
1756
17.1k
    case ALLY_LENGTH_1:
1757
        // got 2nd, of 2, bytes of length
1758
17.1k
        lexer->length += (c << 8);
1759
17.1k
        if (MAX_PACKET_LENGTH <= lexer->length) {
1760
            // bad length
1761
4.14k
            lexer->length = 0;
1762
4.14k
            return character_pushback(lexer, GROUND_STATE);
1763
4.14k
        }  // else
1764
1765
        /* no payload or normal size payload.
1766
         * no idea the real max. */
1767
13.0k
        lexer->state = ALLY_PAYLOAD;
1768
13.0k
        break;
1769
367k
    case ALLY_PAYLOAD:
1770
367k
        if (0 == lexer->length) {
1771
            // got 1st, of 2, bytes of checksum
1772
12.8k
            lexer->state = ALLY_CHECKSUM_A;
1773
12.8k
        } // else stay in payload state
1774
1775
367k
        if (0 < lexer->length) {
1776
            // Pacify Coverity 498037 about underflow
1777
354k
            lexer->length--;
1778
354k
        }  // else something bad happened...
1779
367k
        break;
1780
12.8k
    case ALLY_CHECKSUM_A:
1781
        // got 2nd, of 2, bytes of checksum
1782
12.8k
        lexer->state = ALLY_RECOGNIZED;
1783
12.8k
        break;
1784
8.82k
    case ALLY_RECOGNIZED:
1785
8.82k
        if (0xf1 == c) {   // latin1 small letter N with tilde
1786
790
            lexer->state = ALLY_LEADER_1;
1787
8.03k
        } else if ('$' == c) {  // LEA-5H can/will output NMEA/ALL back to back
1788
1.19k
            lexer->state = NMEA_DOLLAR;
1789
6.84k
        } else if ('{' == c) {
1790
            // codacy thinks this can never happen
1791
858
            return character_pushback(lexer, JSON_LEADER);
1792
5.98k
        } else {
1793
5.98k
            return character_pushback(lexer, GROUND_STATE);
1794
5.98k
        }
1795
1.98k
        break;
1796
    // send ALLYSTAR
1797
1798
    // start CASIC
1799
272k
    case CASIC_LEADER_1:
1800
272k
      if (0xce == c) { // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
1801
            // got 2nd, of 2, bytes of leader
1802
13.5k
            lexer->state = CASIC_LEADER_2;
1803
258k
        } else {
1804
258k
            return character_pushback(lexer, GROUND_STATE);
1805
258k
        }
1806
13.5k
        break;
1807
13.5k
    case CASIC_LEADER_2:
1808
        // got 1st, of 2, bytes of length
1809
13.5k
        lexer->length = (size_t)c;
1810
13.5k
        lexer->state = CASIC_LENGTH_1;
1811
13.5k
        break;
1812
13.5k
    case CASIC_LENGTH_1:
1813
        /* got 2nd, of 2, bytes of length
1814
         * Validate the length field, the driver and code at
1815
         * CASIC_RECOGNIZED require this.
1816
         * Max length seems to be RXM-SVPOS 1536 (packet total 1554)
1817
         * Their doc says payload "<2k bytes"
1818
         */
1819
13.5k
        lexer->length += (c << 8);
1820
13.5k
        if (2048 <= lexer->length ||
1821
8.54k
            0 != (lexer->length % 4)) {
1822
            // bad length
1823
6.38k
            return character_pushback(lexer, GROUND_STATE);
1824
6.38k
        }  // else
1825
1826
        /* no payload or normal size payload. */
1827
7.18k
        lexer->state = CASIC_LENGTH_2;
1828
7.18k
        break;
1829
7.17k
    case CASIC_LENGTH_2:
1830
7.17k
        lexer->state = CASIC_CLASS_ID;
1831
7.17k
        break;
1832
7.16k
    case CASIC_CLASS_ID:
1833
7.16k
        lexer->state = CASIC_MESSAGE_ID;
1834
7.16k
        break;
1835
7.16k
    case CASIC_MESSAGE_ID:
1836
        // We're at the first byte of payload, or the first byte of
1837
        // checksum.  Go directly to CASIC_PAYLOAD.
1838
7.16k
        lexer->state = CASIC_PAYLOAD;
1839
7.16k
        FALLTHROUGH
1840
61.8k
    case CASIC_PAYLOAD:
1841
61.8k
        if (0 == lexer->length) {
1842
            // got 1st, of 4, bytes of checksum
1843
7.08k
            lexer->state = CASIC_CHECKSUM_A;
1844
54.7k
        } else if (2048 <= lexer->length) {
1845
            /* RXM-SVPOS seems to have the longest length: 1552, use 2048
1846
             * Their doc says payload "<2k bytes"
1847
             * how could this happen?
1848
             * stay in payload state */
1849
0
            lexer->length = 0;
1850
54.7k
        } else {
1851
            // more to go, stay in payload state, Coverity 498037
1852
54.7k
            lexer->length--;
1853
54.7k
        }
1854
61.8k
        break;
1855
7.07k
    case CASIC_CHECKSUM_A:
1856
        // got 2nd, of 4, bytes of checksum
1857
7.07k
        lexer->state = CASIC_CHECKSUM_B;
1858
7.07k
        break;
1859
7.06k
    case CASIC_CHECKSUM_B:
1860
        // got 3rd, of 4, bytes of checksum
1861
7.06k
        lexer->state = CASIC_CHECKSUM_C;
1862
7.06k
        break;
1863
7.05k
    case CASIC_CHECKSUM_C:
1864
        // got 4th, of 4, bytes of checksum
1865
7.05k
        lexer->state = CASIC_RECOGNIZED;
1866
7.05k
        break;
1867
3.54k
    case CASIC_RECOGNIZED:
1868
3.54k
        if (0xba == c) {   // latin1 MASCULINE ORDINAL INDICATOR
1869
1.05k
            lexer->state = CASIC_LEADER_1;
1870
2.49k
        } else if ('$' == c) {
1871
            // CASIC can/will output NMEA/CASIC back to back
1872
386
            lexer->state = NMEA_DOLLAR;
1873
2.10k
        } else if ('{' == c) {
1874
            // JSON
1875
506
            return character_pushback(lexer, JSON_LEADER);
1876
506
        }
1877
        // Unknown..
1878
3.03k
        return character_pushback(lexer, GROUND_STATE);
1879
0
        break;
1880
    // end CASIC
1881
0
#ifdef EVERMORE_ENABLE
1882
1.31k
    case EVERMORE_LEADER_1:
1883
1.31k
        if (STX == c) {        // DLE, STX
1884
545
            lexer->state = EVERMORE_LEADER_2;
1885
771
        } else {
1886
771
            return character_pushback(lexer, GROUND_STATE);
1887
771
        }
1888
545
        break;
1889
29.1k
    case EVERMORE_LEADER_2:
1890
29.1k
        lexer->length = (size_t)c;
1891
29.1k
        if (DLE == c) {
1892
5.79k
            lexer->state = EVERMORE_PAYLOAD_DLE;
1893
23.3k
        } else {
1894
23.3k
            lexer->state = EVERMORE_PAYLOAD;
1895
23.3k
        }
1896
29.1k
        break;
1897
487k
    case EVERMORE_PAYLOAD:
1898
487k
        if (DLE == c) {
1899
            // Evermore doubles DLE's
1900
32.3k
            lexer->state = EVERMORE_PAYLOAD_DLE;
1901
455k
        } else if (0 == --lexer->length) {
1902
11.1k
            return character_pushback(lexer, GROUND_STATE);
1903
11.1k
        }
1904
476k
        break;
1905
476k
    case EVERMORE_PAYLOAD_DLE:
1906
38.1k
        switch (c) {
1907
21.5k
        case DLE:
1908
21.5k
            lexer->state = EVERMORE_PAYLOAD;
1909
21.5k
            break;
1910
10.4k
        case ETX:
1911
10.4k
            lexer->state = EVERMORE_RECOGNIZED;
1912
10.4k
            break;
1913
6.08k
        default:
1914
6.08k
            lexer->state = GROUND_STATE;
1915
38.1k
        }
1916
38.1k
        break;
1917
38.1k
    case EVERMORE_RECOGNIZED:
1918
1.84k
        if (DLE == c) {
1919
1.31k
            lexer->state = EVERMORE_LEADER_1;
1920
1.31k
        } else {
1921
532
            return character_pushback(lexer, GROUND_STATE);
1922
532
        }
1923
1.31k
        break;
1924
1.31k
#endif  // EVERMORE_ENABLE
1925
1.31k
#ifdef ITRAX_ENABLE
1926
414k
    case ITALK_LEADER_1:
1927
414k
        if ('!' == c) {      // <!
1928
90.4k
            lexer->state = ITALK_LEADER_2;
1929
323k
        } else {
1930
323k
            return character_pushback(lexer, GROUND_STATE);
1931
323k
        }
1932
90.4k
        break;
1933
90.4k
    case ITALK_LEADER_2:
1934
90.4k
        lexer->length = (size_t)(lexer->inbuffer[6] & 0xff);
1935
90.4k
        lexer->state = ITALK_LENGTH;
1936
90.4k
        break;
1937
90.3k
    case ITALK_LENGTH:
1938
90.3k
        lexer->length += 1;     // fix number of words in payload
1939
90.3k
        lexer->length *= 2;     // convert to number of bytes
1940
90.3k
        lexer->length += 3;     // add trailer length
1941
90.3k
        lexer->state = ITALK_PAYLOAD;
1942
90.3k
        break;
1943
2.92M
    case ITALK_PAYLOAD:
1944
        // lookahead for "<!" because sometimes packets are short but valid
1945
2.92M
        if (('>' == c) &&
1946
44.1k
            ('<' == lexer->inbufptr[0]) &&
1947
8.99k
            ('!' == lexer->inbufptr[1])) {
1948
7.40k
            lexer->state = ITALK_RECOGNIZED;
1949
7.40k
            GPSD_LOG(LOG_PROG, &lexer->errout,
1950
7.40k
                     "ITALK: trying to process runt packet\n");
1951
2.91M
        } else if (0 == --lexer->length) {
1952
81.8k
            lexer->state = ITALK_DELIVERED;
1953
81.8k
        }
1954
2.92M
        break;
1955
81.8k
    case ITALK_DELIVERED:
1956
81.8k
        if ('>' == c) {
1957
17.5k
            lexer->state = ITALK_RECOGNIZED;
1958
64.2k
        } else {
1959
64.2k
            return character_pushback(lexer, GROUND_STATE);
1960
64.2k
        }
1961
17.5k
        break;
1962
21.4k
    case ITALK_RECOGNIZED:
1963
21.4k
        if ('<' == c) {
1964
5.63k
            lexer->state = ITALK_LEADER_1;
1965
15.8k
        } else {
1966
15.8k
            return character_pushback(lexer, GROUND_STATE);
1967
15.8k
        }
1968
5.63k
        break;
1969
5.63k
#endif  // ITRAX_ENABLE
1970
5.63k
#ifdef GEOSTAR_ENABLE
1971
604k
    case GEOSTAR_LEADER_1:
1972
604k
        if ('S' == c) {     // PS
1973
36.0k
            lexer->state = GEOSTAR_LEADER_2;
1974
568k
        } else {
1975
568k
            return character_pushback(lexer, GROUND_STATE);
1976
568k
        }
1977
36.0k
        break;
1978
36.0k
    case GEOSTAR_LEADER_2:
1979
36.0k
        if ('G' == c) {     // PSG
1980
17.4k
            lexer->state = GEOSTAR_LEADER_3;
1981
18.5k
        } else {
1982
18.5k
            return character_pushback(lexer, GROUND_STATE);
1983
18.5k
        }
1984
17.4k
        break;
1985
17.4k
    case GEOSTAR_LEADER_3:
1986
17.4k
        if ('G' == c) {     // PSGG
1987
14.0k
            lexer->state = GEOSTAR_LEADER_4;
1988
14.0k
        } else {
1989
3.44k
            return character_pushback(lexer, GROUND_STATE);
1990
3.44k
        }
1991
14.0k
        break;
1992
14.0k
    case GEOSTAR_LEADER_4:
1993
14.0k
        lexer->state = GEOSTAR_MESSAGE_ID_1;
1994
14.0k
        break;
1995
13.9k
    case GEOSTAR_MESSAGE_ID_1:
1996
13.9k
        lexer->state = GEOSTAR_MESSAGE_ID_2;
1997
13.9k
        break;
1998
13.9k
    case GEOSTAR_MESSAGE_ID_2:
1999
13.9k
        lexer->length = c * 4;
2000
13.9k
        lexer->state = GEOSTAR_LENGTH_1;
2001
13.9k
        break;
2002
13.9k
    case GEOSTAR_LENGTH_1:
2003
13.9k
        lexer->length += (c << 8) * 4;
2004
13.9k
        if (MAX_PACKET_LENGTH < lexer->length) {
2005
4.56k
            lexer->length = 0;
2006
4.56k
            return character_pushback(lexer, GROUND_STATE);
2007
4.56k
        }  // else
2008
9.42k
        lexer->state = GEOSTAR_LENGTH_2;
2009
9.42k
        break;
2010
9.35k
    case GEOSTAR_LENGTH_2:
2011
9.35k
        lexer->state = GEOSTAR_PAYLOAD;
2012
9.35k
        break;
2013
65.8k
    case GEOSTAR_PAYLOAD:
2014
65.8k
        if (0 == --lexer->length) {
2015
7.92k
            lexer->state = GEOSTAR_CHECKSUM_A;
2016
7.92k
        }
2017
        // else stay in payload state
2018
65.8k
        break;
2019
7.90k
    case GEOSTAR_CHECKSUM_A:
2020
7.90k
        lexer->state = GEOSTAR_CHECKSUM_B;
2021
7.90k
        break;
2022
7.90k
    case GEOSTAR_CHECKSUM_B:
2023
7.90k
        lexer->state = GEOSTAR_CHECKSUM_C;
2024
7.90k
        break;
2025
7.89k
    case GEOSTAR_CHECKSUM_C:
2026
7.89k
        lexer->state = GEOSTAR_RECOGNIZED;
2027
7.89k
        break;
2028
5.29k
    case GEOSTAR_RECOGNIZED:
2029
5.29k
        if ('P' == c) {      // P
2030
2.05k
            lexer->state = GEOSTAR_LEADER_1;
2031
3.23k
        } else {
2032
3.23k
            return character_pushback(lexer, GROUND_STATE);
2033
3.23k
        }
2034
2.05k
        break;
2035
2.05k
#endif  // GEOSTAR_ENABLE
2036
2.05k
#ifdef GREIS_ENABLE
2037
13.5k
    case GREIS_EXPECTED:
2038
13.5k
        FALLTHROUGH
2039
34.0k
    case GREIS_RECOGNIZED:
2040
34.0k
        if (!isascii(c)) {
2041
4.33k
            return character_pushback(lexer, GROUND_STATE);
2042
4.33k
        }
2043
29.6k
        if ('#' == c) {
2044
            // Probably a comment used by the testsuite
2045
877
            lexer->state = COMMENT_BODY;
2046
28.7k
        } else if ('\n' == c ||
2047
27.8k
                   '\r' == c) {
2048
            // Arbitrary CR/LF allowed here, so continue to expect GREIS
2049
1.81k
            lexer->state = GREIS_EXPECTED;
2050
1.81k
            character_discard(lexer);
2051
26.9k
        } else {
2052
26.9k
            lexer->state = GREIS_ID_1;
2053
26.9k
        }
2054
29.6k
        break;
2055
434k
    case GREIS_REPLY_1:
2056
434k
        if ('E' != c) {       // RE
2057
407k
            return character_pushback(lexer, GROUND_STATE);
2058
407k
        }
2059
26.9k
        lexer->state = GREIS_REPLY_2;
2060
26.9k
        break;
2061
465k
    case GREIS_ID_1:
2062
465k
        if (!isascii(c)) {
2063
143k
            return character_pushback(lexer, GROUND_STATE);
2064
143k
        }
2065
321k
        lexer->state = GREIS_ID_2;
2066
321k
        break;
2067
26.9k
    case GREIS_REPLY_2:
2068
26.9k
        FALLTHROUGH
2069
348k
    case GREIS_ID_2:
2070
348k
        if (!isxdigit(c)) {
2071
265k
            return character_pushback(lexer, GROUND_STATE);
2072
265k
        }
2073
82.5k
        lexer->length = greis_hex2bin(c) << 8;
2074
82.5k
        lexer->state = GREIS_LENGTH_1;
2075
82.5k
        break;
2076
82.5k
    case GREIS_LENGTH_1:
2077
82.5k
        if (!isxdigit(c)) {
2078
40.2k
            return character_pushback(lexer, GROUND_STATE);
2079
40.2k
        }
2080
42.2k
        lexer->length += greis_hex2bin(c) << 4;
2081
42.2k
        lexer->state = GREIS_LENGTH_2;
2082
42.2k
        break;
2083
42.2k
    case GREIS_LENGTH_2:
2084
42.2k
        if (!isxdigit(c)) {
2085
8.06k
            return character_pushback(lexer, GROUND_STATE);
2086
8.06k
        }
2087
34.1k
        lexer->length += greis_hex2bin(c);
2088
34.1k
        lexer->state = GREIS_PAYLOAD;
2089
34.1k
        break;
2090
880k
    case GREIS_PAYLOAD:
2091
880k
        if (0 == --lexer->length) {
2092
32.5k
            lexer->state = GREIS_RECOGNIZED;
2093
32.5k
        }
2094
        // else stay in payload state
2095
880k
        break;
2096
0
#endif  // GREIS_ENABLE
2097
0
#ifdef TSIP_ENABLE
2098
0
    case TSIP_LEADER:
2099
        // unused case. see TSIP_RECOGNIZED
2100
0
        if (0x13 <= c) {       // DC3
2101
0
            lexer->length = TSIP_MAX_PACKET;
2102
0
            lexer->state = TSIP_PAYLOAD;
2103
0
        } else {
2104
0
            return character_pushback(lexer, GROUND_STATE);
2105
0
        }
2106
0
        break;
2107
19.0M
    case TSIP_PAYLOAD:
2108
19.0M
        if (DLE == c) {
2109
583k
            lexer->state = TSIP_DLE;
2110
583k
        }
2111
19.0M
        if (0 == --lexer->length ) {
2112
            // uh, oh, packet too long, probably was never TSIP
2113
            // note lexer->length is unsigned
2114
17.8k
            lexer->state = GROUND_STATE;
2115
17.8k
        }
2116
19.0M
        break;
2117
583k
    case TSIP_DLE:
2118
583k
        switch (c) {
2119
101k
        case ETX:
2120
101k
            lexer->state = TSIP_RECOGNIZED;
2121
101k
            break;
2122
399k
        case DLE:
2123
399k
            lexer->length = TSIP_MAX_PACKET;
2124
399k
            lexer->state = TSIP_PAYLOAD;
2125
399k
            break;
2126
81.8k
        default:
2127
81.8k
            lexer->state = GROUND_STATE;
2128
81.8k
            break;
2129
583k
        }
2130
583k
        break;
2131
583k
    case TSIP_RECOGNIZED:
2132
59.5k
        if (DLE == c) {
2133
            /*
2134
             * Don't go to TSIP_LEADER state -- TSIP packets aren't
2135
             * checksummed, so false positives are easy.  We might be
2136
             * looking at another DLE-stuffed protocol like EverMore
2137
             * or Garmin streaming binary.
2138
             */
2139
21.6k
            lexer->state = DLE_LEADER;
2140
37.9k
        } else {
2141
37.9k
            return character_pushback(lexer, GROUND_STATE);
2142
37.9k
        }
2143
21.6k
        break;
2144
21.6k
#endif  // TSIP_ENABLE
2145
458k
    case RTCM2_SYNC_STATE:
2146
458k
        FALLTHROUGH
2147
458k
    case RTCM2_SKIP_STATE:
2148
458k
        if (ISGPS_MESSAGE == (isgpsstat = rtcm2_decode(lexer, c))) {
2149
5.99k
            lexer->state = RTCM2_RECOGNIZED;
2150
452k
        } else if (ISGPS_NO_SYNC == isgpsstat) {
2151
24.1k
            lexer->state = GROUND_STATE;
2152
24.1k
        }
2153
458k
        break;
2154
2155
14.6k
    case RTCM2_RECOGNIZED:
2156
14.6k
        if ('#' == c) {
2157
            /*
2158
             * There's a remote possibility this could fire when # =
2159
             * 0x23 is legitimate in-stream RTCM2 data.  No help for
2160
             * it, the test framework needs this case so it can inject
2161
             * # EOF and we'll miss a packet.
2162
             */
2163
572
            return character_pushback(lexer, GROUND_STATE);
2164
572
        }
2165
14.0k
        if (ISGPS_SYNC == rtcm2_decode(lexer, c)) {
2166
9.66k
            lexer->state = RTCM2_SYNC_STATE;
2167
9.66k
        } else {
2168
4.43k
            lexer->state = GROUND_STATE;
2169
4.43k
        }
2170
14.0k
        break;
2171
140M
    case JSON_LEADER:
2172
140M
        switch (c) {
2173
139M
        case '{':
2174
139M
            FALLTHROUGH
2175
140M
        case '[':
2176
140M
            lexer->json_depth++;
2177
140M
            break;
2178
60.1k
        case '}':
2179
60.1k
            FALLTHROUGH
2180
123k
        case ']':
2181
123k
            if (0 == --lexer->json_depth) {
2182
8.37k
                lexer->state = JSON_RECOGNIZED;
2183
8.37k
            }
2184
123k
            break;
2185
19.9k
        case ',':
2186
19.9k
            break;
2187
81.0k
        case '"':
2188
81.0k
            lexer->state = JSON_STRINGLITERAL;
2189
81.0k
            lexer->json_after = JSON_END_ATTRIBUTE;
2190
81.0k
            break;
2191
200k
        default:
2192
200k
            if (isspace(c)) {
2193
78.6k
                break;
2194
78.6k
            }
2195
121k
            GPSD_LOG(LOG_RAW1, &lexer->errout,
2196
121k
                     "%08ld: missing attribute start after header\n",
2197
121k
                     lexer->char_counter);
2198
121k
            lexer->state = GROUND_STATE;
2199
140M
        }
2200
140M
        break;
2201
140M
    case JSON_STRINGLITERAL:
2202
4.62M
        if ('\\' == c) {
2203
5.27k
            lexer->state = JSON_STRING_SOLIDUS;
2204
4.61M
        } else if ('"' == c) {
2205
81.3k
            lexer->state = lexer->json_after;
2206
81.3k
        }
2207
4.62M
        break;
2208
5.27k
    case JSON_STRING_SOLIDUS:
2209
5.27k
        lexer->state = JSON_STRINGLITERAL;
2210
5.27k
        break;
2211
84.8k
    case JSON_END_ATTRIBUTE:
2212
84.8k
        if (isspace(c)) {
2213
4.11k
            break;
2214
4.11k
        }
2215
80.6k
        if (':' == c) {
2216
59.4k
            lexer->state = JSON_EXPECT_VALUE;
2217
59.4k
        } else {
2218
            // saw something other than value start after colon
2219
21.2k
            return character_pushback(lexer, GROUND_STATE);
2220
21.2k
        }
2221
59.4k
        break;
2222
60.9k
    case JSON_EXPECT_VALUE:
2223
60.9k
        if (isspace(c)) {
2224
1.50k
            break;
2225
1.50k
        }
2226
59.4k
        switch (c) {
2227
696
        case '"':
2228
696
            lexer->state = JSON_STRINGLITERAL;
2229
696
            lexer->json_after = JSON_END_VALUE;
2230
696
            break;
2231
28.0k
        case '{':
2232
28.0k
            FALLTHROUGH
2233
28.4k
        case '[':
2234
28.4k
            return character_pushback(lexer, JSON_LEADER);
2235
0
            break;
2236
3.03k
        case '-':
2237
3.03k
            FALLTHROUGH
2238
4.33k
        case '0':
2239
4.33k
            FALLTHROUGH
2240
5.44k
        case '1':
2241
5.44k
            FALLTHROUGH
2242
6.67k
        case '2':
2243
6.67k
            FALLTHROUGH
2244
7.78k
        case '3':
2245
7.78k
            FALLTHROUGH
2246
8.71k
        case '4':
2247
8.71k
            FALLTHROUGH
2248
9.35k
        case '5':
2249
9.35k
            FALLTHROUGH
2250
19.1k
        case '6':
2251
19.1k
            FALLTHROUGH
2252
19.8k
        case '7':
2253
19.8k
            FALLTHROUGH
2254
20.5k
        case '8':
2255
20.5k
            FALLTHROUGH
2256
21.5k
        case '9':
2257
21.5k
            lexer->state = JSON_NUMBER;
2258
21.5k
            break;
2259
889
        case 'f':
2260
889
            FALLTHROUGH
2261
1.40k
        case 'n':
2262
1.40k
            FALLTHROUGH
2263
2.20k
        case 't':
2264
            /*
2265
             * This is a bit more permissive than strictly necessary, as
2266
             * GPSD JSON does not include the null token.  Still, it's
2267
             * futureproofing.
2268
             */
2269
2.20k
            lexer->state = JSON_SPECIAL;
2270
2.20k
            break;
2271
6.54k
        default:
2272
            // couldn't recognize start of value literal
2273
6.54k
            return character_pushback(lexer, GROUND_STATE);
2274
59.4k
        }
2275
24.4k
        break;
2276
31.1k
    case JSON_NUMBER:
2277
        /*
2278
         * Will recognize some ill-formed numeric literals.
2279
         * Should be OK as we're already three stages deep inside
2280
         * JSON recognition; odds that we'll actually see an
2281
         * ill-formed literal are quite low. and the worst
2282
         * possible result if it happens is our JSON parser will
2283
         * quietly chuck out the object.
2284
         */
2285
31.1k
        if (NULL == strchr("1234567890.eE+-", c)) {
2286
21.5k
            return character_pushback(lexer, JSON_END_VALUE);
2287
21.5k
        }
2288
9.59k
        break;
2289
9.59k
    case JSON_SPECIAL:
2290
3.97k
        if (NULL == strchr("truefalsnil", c)) {
2291
2.19k
            return character_pushback(lexer, JSON_END_VALUE);
2292
2.19k
        }
2293
1.77k
        break;
2294
25.3k
    case JSON_END_VALUE:
2295
25.3k
        if (isspace(c)) {
2296
1.00k
            break;
2297
1.00k
        }
2298
24.3k
        if ('}' == c ||
2299
22.1k
            ']' == c) {
2300
13.0k
            return character_pushback(lexer, JSON_LEADER);
2301
13.0k
        }
2302
11.3k
        if (',' != c) {
2303
            // trailing garbage after JSON value
2304
10.5k
            return character_pushback(lexer, GROUND_STATE);
2305
10.5k
        }
2306
845
        lexer->state = JSON_LEADER;
2307
845
        break;
2308
0
#ifdef STASH_ENABLE
2309
17.9k
    case STASH_RECOGNIZED:
2310
17.9k
        if ('$' != c) {
2311
0
            return character_pushback(lexer, GROUND_STATE);
2312
0
        }
2313
17.9k
        lexer->state = NMEA_DOLLAR;
2314
17.9k
        break;
2315
613M
#endif  // STASH_ENABLE
2316
613M
    }
2317
2318
    /* Catch length overflow.  Should not happen.
2319
     * length is size_t, so underflow looks like overflow too. */
2320
451M
    if (MAX_PACKET_LENGTH <= lexer->length) {
2321
51.7k
        GPSD_LOG(LOG_WARN, &lexer->errout,
2322
51.7k
                 "Too long: %zu state %u %s c x%x\n",
2323
51.7k
                 lexer->length, lexer->state, state_table[lexer->state], c);
2324
        // exit(255);
2325
51.7k
        lexer->length = 0;
2326
51.7k
        return character_pushback(lexer, GROUND_STATE);
2327
51.7k
    }
2328
451M
    return true;        // no pushback
2329
451M
}
2330
2331
// packet grab succeeded, move to output buffer
2332
static void packet_accept(struct gps_lexer_t *lexer, int packet_type)
2333
462k
{
2334
462k
    size_t packetlen = lexer->inbufptr - lexer->inbuffer;
2335
2336
462k
    if (sizeof(lexer->outbuffer) > packetlen) {
2337
462k
        char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
2338
2339
462k
        memcpy(lexer->outbuffer, lexer->inbuffer, packetlen);
2340
462k
        lexer->outbuflen = packetlen;
2341
462k
        lexer->outbuffer[packetlen] = '\0';
2342
462k
        lexer->type = packet_type;
2343
462k
        GPSD_LOG(LOG_RAW1, &lexer->errout,
2344
462k
                 "Packet type %d accepted %zu = %s\n",
2345
462k
                 packet_type, packetlen,
2346
462k
                 gpsd_packetdump(scratchbuf,  sizeof(scratchbuf),
2347
462k
                                 lexer->outbuffer,
2348
462k
                                 lexer->outbuflen));
2349
462k
    } else {
2350
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
2351
0
                 "Rejected too long packet type %d len %zu\n",
2352
0
                 packet_type, packetlen);
2353
0
    }
2354
462k
}
2355
2356
// shift the input buffer to discard all data up to current input pointer
2357
static void packet_discard(struct gps_lexer_t *lexer)
2358
480k
{
2359
480k
    size_t discard = lexer->inbufptr - lexer->inbuffer;
2360
480k
    size_t remaining = lexer->inbuflen - discard;
2361
480k
    char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
2362
2363
480k
    if (sizeof(lexer->inbuffer) < discard) {
2364
        // Huh?
2365
0
        GPSD_LOG(LOG_WARN, &lexer->errout,
2366
0
                 "packet_discard() of %zu??\n", discard);
2367
0
        lexer->inbufptr = lexer->inbuffer;
2368
0
        lexer->inbuflen = 0;
2369
0
        return;
2370
0
    }  // else
2371
2372
480k
    lexer->inbufptr = memmove(lexer->inbuffer, lexer->inbufptr, remaining);
2373
480k
    lexer->inbuflen = remaining;
2374
2375
480k
    GPSD_LOG(LOG_RAW1, &lexer->errout,
2376
480k
             "packet_discard() of %zu, chars remaining is %zu = %s\n",
2377
480k
             discard, remaining,
2378
480k
             gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
2379
480k
                             lexer->inbuffer, lexer->inbuflen));
2380
480k
}
2381
2382
#ifdef STASH_ENABLE
2383
// See test/daemon/isync.log for why the stash is needed.
2384
2385
// stash the input buffer up to current input pointer
2386
static void packet_stash(struct gps_lexer_t *lexer)
2387
17.9k
{
2388
17.9k
    size_t stashlen = lexer->inbufptr - lexer->inbuffer;
2389
2390
17.9k
    if (sizeof(lexer->stashbuffer) < stashlen) {
2391
        // too big!
2392
0
        stashlen = 0;
2393
0
        lexer->stashbuffer[0] = '\0';
2394
0
        GPSD_LOG(LOG_WARN, &lexer->errout,
2395
0
                 "packet_stash: too big, discarding.\n");
2396
17.9k
    } else {
2397
17.9k
        char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
2398
2399
17.9k
        memcpy(lexer->stashbuffer, lexer->inbuffer, stashlen);
2400
2401
17.9k
        GPSD_LOG(LOG_RAW1, &lexer->errout,
2402
17.9k
                 "Packet stash of %zu = %s\n",
2403
17.9k
                 stashlen,
2404
17.9k
                 gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
2405
17.9k
                                 lexer->stashbuffer, stashlen));
2406
17.9k
    }
2407
17.9k
    lexer->stashbuflen = stashlen;
2408
17.9k
}
2409
2410
// return stash to start of input buffer
2411
static void packet_unstash(struct gps_lexer_t *lexer)
2412
7.65k
{
2413
7.65k
    size_t available = sizeof(lexer->inbuffer) - lexer->inbuflen;
2414
7.65k
    size_t stashlen = lexer->stashbuflen;
2415
2416
7.65k
    if (stashlen <= available) {
2417
7.65k
        char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
2418
2419
7.65k
        memmove(lexer->inbuffer + stashlen, lexer->inbuffer, lexer->inbuflen);
2420
7.65k
        memcpy(lexer->inbuffer, lexer->stashbuffer, stashlen);
2421
7.65k
        lexer->inbuflen += stashlen;
2422
7.65k
        lexer->stashbuflen = 0;
2423
2424
7.65k
        GPSD_LOG(LOG_RAW1, &lexer->errout,
2425
7.65k
                 "Packet unstash of %zu, reconstructed is %zu = %s\n",
2426
7.65k
                 stashlen, lexer->inbuflen,
2427
7.65k
                 gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
2428
7.65k
                                 lexer->inbuffer, lexer->inbuflen));
2429
7.65k
    } else {
2430
0
        GPSD_LOG(LOG_WARN, &lexer->errout,
2431
0
                 "Rejected too long unstash of %zu\n", stashlen);
2432
0
        lexer->stashbuflen = 0;
2433
0
    }
2434
7.65k
}
2435
#endif  // STASH_ENABLE
2436
2437
// entry points begin here
2438
2439
// reset lexer structure
2440
void lexer_init(struct gps_lexer_t *lexer, struct gpsd_errout_t *errout)
2441
53.5k
{
2442
53.5k
    memset(lexer, 0, sizeof(struct gps_lexer_t));
2443
    /* let memset() do all the zeros
2444
     *
2445
     *  lexer->char_counter = 0;
2446
     *  lexer->retry_counter = 0;
2447
     *  lexer->json_depth = 0;
2448
     *  lexer->start_time.tv_sec = 0;
2449
     *  lexer->start_time.tv_nsec = 0;
2450
     */
2451
    // set start_time to help out autobaud.
2452
53.5k
    (void)clock_gettime(CLOCK_REALTIME, &lexer->start_time);
2453
    // No SPARTN decode by default.
2454
53.5k
    lexer->type_mask =  PACKET_TYPEMASK(SPARTN_PACKET);
2455
53.5k
    packet_reset(lexer);
2456
53.5k
    lexer->errout = *errout;    // srtucture copy
2457
53.5k
}
2458
2459
// grab one packet from inbufptr
2460
// move it to outbuffer[0], set outbuflen, and add a NUL.
2461
// adjust pointers and lengths, then return
2462
void packet_parse(struct gps_lexer_t *lexer)
2463
498k
{
2464
2465
498k
    lexer->outbuflen = 0;
2466
613M
    while (0 < packet_buffered_input(lexer)) {
2467
613M
        unsigned char c = *lexer->inbufptr++;
2468
613M
        unsigned int oldstate = lexer->state;
2469
613M
        unsigned inbuflen;      // bytes in inbuffer for message
2470
613M
        unsigned idx;           // index into inbuffer
2471
613M
        unsigned crc_computed;  // the CRC/checksum we computed
2472
613M
        unsigned crc_expected;  // the CRC/checksum the message claims to have
2473
613M
        enum {PASS, ACCEPT} acc_dis;
2474
613M
        int packet_type;        // gpsd packet type
2475
613M
        unsigned pkt_id;        // native type or ID the message thinks it is
2476
613M
        unsigned data_len;      // What the message says the data length is.
2477
613M
        unsigned char ck_a, ck_b;  // for ubx check bytes
2478
613M
#ifdef STASH_ENABLE
2479
613M
        bool unstash = false;
2480
613M
#endif  //  STASH_ENABLE
2481
2482
613M
        if (!nextstate(lexer, c)) {
2483
162M
            continue;
2484
162M
        }
2485
451M
        GPSD_LOG(LOG_RAW, &lexer->errout,
2486
451M
                 "%08ld: character '%c' [%02x], %s -> %s\n",
2487
451M
                 lexer->char_counter, (isprint(c) ? c : '.'), c,
2488
451M
                 state_table[oldstate], state_table[lexer->state]);
2489
451M
        lexer->char_counter++;
2490
451M
        inbuflen = lexer->inbufptr - lexer->inbuffer;
2491
451M
        acc_dis = PASS;
2492
2493
        /* check if we have a _RECOGNISED state, if so, perform final
2494
         * checks on the packet, before decoding.
2495
         * Cases alpha sorted to be easy to find. */
2496
451M
        switch (lexer->state) {
2497
27.9k
        case AIS_RECOGNIZED:
2498
27.9k
            acc_dis = ACCEPT;
2499
27.9k
            if (!nmea_checksum(&lexer->errout,
2500
27.9k
                               (const char *)lexer->inbuffer,
2501
27.9k
                               (const char *)lexer->inbufptr)) {
2502
5.88k
                packet_type = BAD_PACKET;
2503
5.88k
                lexer->state = GROUND_STATE;
2504
5.88k
                break;
2505
5.88k
            }
2506
22.0k
            packet_type = AIVDM_PACKET;
2507
22.0k
            break;
2508
2509
12.8k
        case ALLY_RECOGNIZED:
2510
            // ALLYSTAR use a TCP like checksum, 8-bit Fletcher Algorithm
2511
12.8k
            ck_a = (unsigned char)0;
2512
12.8k
            ck_b = (unsigned char)0;
2513
            // payload length
2514
12.8k
            data_len = getleu16(lexer->inbuffer, 4);
2515
2516
12.8k
            GPSD_LOG(LOG_IO, &lexer->errout, "ALLY: buflen %d. paylen %u\n",
2517
12.8k
                     inbuflen, data_len);
2518
12.8k
            if (inbuflen < (data_len + 8)) {
2519
519
                GPSD_LOG(LOG_INFO, &lexer->errout,
2520
519
                         "ALLY: bad length %d/%u\n",
2521
519
                         inbuflen, data_len);
2522
519
                packet_type = BAD_PACKET;
2523
519
                lexer->state = GROUND_STATE;
2524
519
                acc_dis = ACCEPT;
2525
519
                break;
2526
519
            }
2527
            // from class ID (byte 2), msg ID, length,  to end of payload
2528
405k
            for (idx = 0; idx < (data_len + 4); idx++) {
2529
393k
                ck_a += lexer->inbuffer[idx + 2];
2530
393k
                ck_b += ck_a;
2531
393k
            }
2532
12.3k
            if (ck_a == lexer->inbuffer[data_len + 6] &&
2533
9.65k
                ck_b == lexer->inbuffer[data_len + 7]) {
2534
8.89k
                packet_type = ALLYSTAR_PACKET;
2535
8.89k
            } else {
2536
3.46k
                char scratchbuf[200];
2537
2538
3.46k
                GPSD_LOG(LOG_WARN, &lexer->errout,
2539
3.46k
                         "ALLY: bad checksum 0x%02hhx%02hhx length %d/%u"
2540
3.46k
                         ", %s\n",
2541
3.46k
                         ck_a,
2542
3.46k
                         ck_b,
2543
3.46k
                         inbuflen, data_len,
2544
3.46k
                         gps_hexdump(scratchbuf, sizeof(scratchbuf),
2545
3.46k
                                     lexer->inbuffer, lexer->inbuflen));
2546
3.46k
                packet_type = BAD_PACKET;
2547
3.46k
                lexer->state = GROUND_STATE;
2548
3.46k
            }
2549
12.3k
            acc_dis = ACCEPT;
2550
12.3k
            break;
2551
2552
7.05k
        case CASIC_RECOGNIZED:
2553
            /* Payload length.  This field has already been partially
2554
             * validated in nextstate().  */
2555
7.05k
            data_len = getleu16(lexer->inbuffer, 2);
2556
7.05k
            if (inbuflen < (data_len + 10)) {
2557
887
                GPSD_LOG(LOG_INFO, &lexer->errout,
2558
887
                         "CASIC: bad length %d/%u\n",
2559
887
                         inbuflen, data_len);
2560
887
                packet_type = BAD_PACKET;
2561
887
                lexer->state = GROUND_STATE;
2562
887
                acc_dis = ACCEPT;
2563
887
                break;
2564
887
            }
2565
6.16k
            crc_computed = casic_checksum(lexer->inbuffer + 2, data_len + 4);
2566
6.16k
            crc_expected = getleu32(lexer->inbuffer, data_len + 6);
2567
6.16k
            if (crc_computed == crc_expected) {
2568
3.62k
                packet_type = CASIC_PACKET;
2569
3.62k
            } else {
2570
2.54k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2571
2.54k
                         "CASIC checksum 0x%04x over length %d,"
2572
2.54k
                         " expecting 0x%04x (type 0x%02hhx%02hhx)\n",
2573
2.54k
                         crc_computed,
2574
2.54k
                         data_len + 4,
2575
2.54k
                         crc_expected,
2576
2.54k
                         lexer->inbuffer[4], lexer->inbuffer[5]);
2577
2.54k
                packet_type = BAD_PACKET;
2578
2.54k
                lexer->state = GROUND_STATE;
2579
2.54k
            }
2580
6.16k
            acc_dis = ACCEPT;
2581
6.16k
            break;
2582
2583
11.2k
        case COMMENT_RECOGNIZED:
2584
11.2k
            packet_type = COMMENT_PACKET;
2585
11.2k
            acc_dis = ACCEPT;
2586
11.2k
            lexer->state = GROUND_STATE;
2587
11.2k
            break;
2588
2589
0
#ifdef EVERMORE_ENABLE
2590
10.4k
        case EVERMORE_RECOGNIZED:
2591
            // Evermore uses DLE stuffing, what a PITA.
2592
            // Assume failure.
2593
10.4k
            packet_type = BAD_PACKET;
2594
10.4k
            acc_dis = ACCEPT;
2595
10.4k
            lexer->state = GROUND_STATE;
2596
2597
10.4k
            do {
2598
                // the do{} is only done once, just so we can break
2599
2600
                // check for leader
2601
10.4k
                idx = 0;
2602
10.4k
                if (DLE != lexer->inbuffer[idx++] ||
2603
9.77k
                    STX != lexer->inbuffer[idx++]) {
2604
                    // should not happen
2605
1.10k
                    break;
2606
1.10k
                }
2607
2608
                // get one byte length, if length is 0x10, two DLE are sent.
2609
9.35k
                data_len = lexer->inbuffer[idx++];
2610
9.35k
                if (DLE == data_len &&
2611
2.59k
                    DLE != lexer->inbuffer[idx++]) {
2612
                    // should not happen
2613
1.85k
                    break;
2614
1.85k
                }
2615
7.49k
                if (8 > data_len) {
2616
                    /* should not happen, need 1 byte of data for message ID
2617
                     * shortest message is 8 bytes of data_len */
2618
532
                    break;
2619
532
                }
2620
2621
6.96k
                data_len -= 2;
2622
6.96k
                crc_computed = 0;
2623
27.8k
                for (; data_len > 0; data_len--) {
2624
26.7k
                    crc_computed += lexer->inbuffer[idx];
2625
26.7k
                    if (DLE == lexer->inbuffer[idx++] &&
2626
6.69k
                        DLE != lexer->inbuffer[idx++]) {
2627
                        // should not happen, DLE not doubled.
2628
5.80k
                        break;
2629
5.80k
                    }
2630
26.7k
                }
2631
                // get one byte checksum
2632
6.96k
                crc_expected = lexer->inbuffer[idx++];
2633
6.96k
                if (DLE == crc_expected &&
2634
3.84k
                    DLE != lexer->inbuffer[idx++]) {
2635
                    // should not happen, DLE not doubled.
2636
2.57k
                    break;
2637
2.57k
                }
2638
                // get two byte trailer
2639
4.38k
                if (DLE != lexer->inbuffer[idx++] ||
2640
3.07k
                    ETX != lexer->inbuffer[idx]) {
2641
                    // we used to say n++ here, but scan-build complains
2642
                    // bad trailer
2643
1.84k
                    break;
2644
1.84k
                }
2645
2.54k
                crc_computed &= 0xff;
2646
2.54k
                if (crc_computed != crc_expected) {
2647
656
                    GPSD_LOG(LOG_PROG, &lexer->errout,
2648
656
                             "EverMore checksum failed: %02x != %02x\n",
2649
656
                             crc_computed, crc_expected);
2650
656
                    break;
2651
656
                }
2652
1.88k
                packet_type = EVERMORE_PACKET;
2653
1.88k
                lexer->state = EVERMORE_RECOGNIZED;
2654
1.88k
                break;     // redundant
2655
2.54k
            } while (0);
2656
10.4k
            break;
2657
0
#endif  // EVERMORE_ENABLE
2658
2659
0
#ifdef GEOSTAR_ENABLE
2660
7.89k
        case GEOSTAR_RECOGNIZED:
2661
            // GeoStar uses a XOR 32bit checksum
2662
7.89k
            acc_dis = ACCEPT;
2663
7.89k
            crc_computed = 0;
2664
2665
            // Calculate checksum
2666
51.9k
            for (idx = 0; idx < inbuflen; idx += 4) {
2667
44.0k
                crc_computed ^= getleu32(lexer->inbuffer, idx);
2668
44.0k
            }
2669
2670
7.89k
            if (0 != crc_computed) {
2671
2.39k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2672
2.39k
                         "GeoStar checksum failed 0x%x over length %d\n",
2673
2.39k
                         crc_computed, inbuflen);
2674
2.39k
                packet_type = BAD_PACKET;
2675
2.39k
                lexer->state = GROUND_STATE;
2676
2.39k
                break;
2677
2.39k
            }
2678
5.49k
            packet_type = GEOSTAR_PACKET;
2679
5.49k
            break;
2680
0
#endif  // GEOSTAR_ENABLE
2681
2682
0
#ifdef GREIS_ENABLE
2683
32.5k
        case GREIS_RECOGNIZED:
2684
32.5k
            acc_dis = ACCEPT;
2685
2686
32.5k
            if ('R' == lexer->inbuffer[0] &&
2687
13.7k
                'E' == lexer->inbuffer[1]) {
2688
                // Replies don't have checksum
2689
11.2k
                GPSD_LOG(LOG_IO, &lexer->errout,
2690
11.2k
                         "Accept GREIS reply packet len %d\n", inbuflen);
2691
11.2k
                packet_type = GREIS_PACKET;
2692
11.2k
                break;
2693
11.2k
            }
2694
21.2k
            if ('E' == lexer->inbuffer[0] &&
2695
3.53k
                'R' == lexer->inbuffer[1]) {
2696
                // Error messages don't have checksum
2697
447
                GPSD_LOG(LOG_IO, &lexer->errout,
2698
447
                         "Accept GREIS error packet len %d\n", inbuflen);
2699
447
                packet_type = GREIS_PACKET;
2700
447
                break;
2701
447
            }
2702
            // 8-bit checksum
2703
20.8k
            crc_computed = greis_checksum(lexer->inbuffer, inbuflen);
2704
2705
20.8k
            if (0 != crc_computed) {
2706
                /*
2707
                 * Print hex instead of raw characters, since they might be
2708
                 * unprintable. If \0, it will even mess up the log output.
2709
                 */
2710
11.9k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2711
11.9k
                         "REJECT GREIS len %d."
2712
11.9k
                         " Bad checksum %#02x, expecting 0."
2713
11.9k
                         " Packet type in hex: 0x%02x%02x",
2714
11.9k
                         inbuflen, crc_computed,
2715
11.9k
                         lexer->inbuffer[0],
2716
11.9k
                         lexer->inbuffer[1]);
2717
11.9k
                packet_type = BAD_PACKET;
2718
                // got this far, fair to expect we will get more GREIS
2719
11.9k
                lexer->state = GREIS_EXPECTED;
2720
11.9k
                break;
2721
11.9k
            }
2722
8.84k
            GPSD_LOG(LOG_IO, &lexer->errout,
2723
8.84k
                     "Accept GREIS packet type '%c%c' len %d\n",
2724
8.84k
                     lexer->inbuffer[0], lexer->inbuffer[1], inbuflen);
2725
8.84k
            packet_type = GREIS_PACKET;
2726
8.84k
            break;
2727
0
#endif  // GREIS_ENABLE
2728
2729
11.9M
        case GROUND_STATE:
2730
11.9M
            character_discard(lexer);
2731
11.9M
            break;
2732
2733
#ifdef GARMINTXT_ENABLE
2734
        case GTXT_RECOGNIZED:
2735
            // As of June 2023, we have no regression of GARMINTXT.
2736
            if (57 <= inbuflen) {
2737
                packet_accept(lexer, GARMINTXT_PACKET);
2738
                packet_discard(lexer);
2739
                lexer->state = GROUND_STATE;
2740
            } else {
2741
                packet_accept(lexer, BAD_PACKET);
2742
                lexer->state = GROUND_STATE;
2743
            }
2744
            break;
2745
#endif
2746
2747
0
#ifdef ITRAX_ENABLE
2748
588k
#define getib(j) ((uint8_t)lexer->inbuffer[(j)])
2749
294k
#define getiw(i) ((uint16_t)(((uint16_t)getib((i) + 1) << 8) | \
2750
294k
                             (uint16_t)getib((i))))
2751
2752
24.9k
        case ITALK_RECOGNIZED:
2753
            // number of words
2754
24.9k
            data_len = lexer->inbuffer[6] & 0xff;
2755
2756
            // expected checksum
2757
24.9k
            crc_expected = getiw(7 + 2 * data_len);
2758
2759
24.9k
            crc_computed = 0;
2760
294k
            for (idx = 0; idx < data_len; idx++) {
2761
269k
                uint16_t tmpw = getiw(7 + 2 * idx);
2762
269k
                uint32_t tmpdw  = (crc_computed + 1) * (tmpw + idx);
2763
269k
                crc_computed ^= (tmpdw & 0xffff) ^ ((tmpdw >> 16) & 0xffff);
2764
269k
            }
2765
24.9k
            if (0 == data_len ||
2766
21.5k
                crc_computed == crc_expected) {
2767
21.5k
                packet_type = ITALK_PACKET;
2768
21.5k
            } else {
2769
3.39k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2770
3.39k
                         "ITALK: checksum failed - "
2771
3.39k
                         "type 0x%02x expected 0x%04x got 0x%04x\n",
2772
3.39k
                         lexer->inbuffer[4], crc_expected, crc_computed);
2773
3.39k
                packet_type = BAD_PACKET;
2774
3.39k
                lexer->state = GROUND_STATE;
2775
3.39k
            }
2776
24.9k
            acc_dis = ACCEPT;
2777
24.9k
#undef getiw
2778
24.9k
#undef getib
2779
24.9k
            break;
2780
0
#endif  // ITRAX_ENABLE
2781
2782
8.37k
        case JSON_RECOGNIZED:
2783
8.37k
            if (11 <= inbuflen) {
2784
                // {"class": }
2785
444
                packet_type = JSON_PACKET;
2786
7.92k
            } else {
2787
7.92k
                packet_type = BAD_PACKET;
2788
7.92k
            }
2789
8.37k
            lexer->state = GROUND_STATE;
2790
8.37k
            acc_dis = ACCEPT;
2791
8.37k
            break;
2792
2793
0
#ifdef NAVCOM_ENABLE
2794
9.48k
        case NAVCOM_RECOGNIZED:
2795
            // By the time we got here we know checksum is OK
2796
9.48k
            packet_type = NAVCOM_PACKET;
2797
9.48k
            acc_dis = ACCEPT;
2798
9.48k
            break;
2799
0
#endif  // NAVCOM_ENABLE
2800
2801
100k
        case NMEA_RECOGNIZED:
2802
100k
            if (nmea_checksum(&lexer->errout,
2803
100k
                              (const char *)lexer->inbuffer,
2804
100k
                              (const char *)lexer->inbufptr)) {
2805
74.6k
                packet_type = NMEA_PACKET;
2806
74.6k
#ifdef STASH_ENABLE
2807
74.6k
                unstash = true;
2808
74.6k
#endif  // STASH_ENABLE
2809
74.6k
            } else {
2810
25.5k
                lexer->state = GROUND_STATE;
2811
25.5k
                packet_type = BAD_PACKET;
2812
25.5k
            }
2813
100k
            acc_dis = ACCEPT;
2814
100k
            break;
2815
2816
0
#ifdef ONCORE_ENABLE
2817
8.62k
        case ONCORE_RECOGNIZED:
2818
8.62k
            acc_dis = ACCEPT;
2819
8.62k
            crc_computed = 0;
2820
519k
            for (idx = 2; idx < inbuflen - 2; idx++) {
2821
510k
                crc_computed ^= lexer->inbuffer[idx];
2822
510k
            }
2823
2824
8.62k
            if (0 != crc_computed) {
2825
1.35k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2826
1.35k
                         "REJECT OnCore packet @@%c%c len %d\n",
2827
1.35k
                         lexer->inbuffer[2], lexer->inbuffer[3], inbuflen);
2828
1.35k
                lexer->state = GROUND_STATE;
2829
1.35k
                packet_type = BAD_PACKET;
2830
1.35k
                break;
2831
1.35k
            }
2832
7.26k
            GPSD_LOG(LOG_IO, &lexer->errout,
2833
7.26k
                     "Accept OnCore packet @@%c%c len %d\n",
2834
7.26k
                     lexer->inbuffer[2], lexer->inbuffer[3], inbuflen);
2835
7.26k
            packet_type = ONCORE_PACKET;
2836
7.26k
            break;
2837
0
#endif  // ONCORE_ENABLE
2838
2839
14.8k
        case RTCM2_RECOGNIZED:
2840
            /*
2841
             * RTCM packets don't have checksums.  The six bits of parity
2842
             * per word and the preamble better be good enough.
2843
             */
2844
14.8k
            packet_type = RTCM2_PACKET;
2845
14.8k
            acc_dis = ACCEPT;
2846
14.8k
            break;
2847
2848
11.1k
        case RTCM3_RECOGNIZED:
2849
            // RTCM3 message header not always at inbuffer[0]
2850
168k
            for (idx = 0; idx < inbuflen; idx++) {
2851
168k
                if (0xd3 == lexer->inbuffer[idx]) {
2852
11.1k
                    break;
2853
11.1k
                }
2854
168k
            }
2855
11.1k
            if (idx + 3 > inbuflen ||
2856
11.1k
                2048 < idx) {
2857
30
                GPSD_LOG(LOG_WARN, &lexer->errout,
2858
30
                         "RTCM3 preamble not found in buffer "
2859
30
                         "(idx %u inbuflen %u), dropping.\n",
2860
30
                         idx, inbuflen);
2861
30
                packet_type = BAD_PACKET;
2862
30
                acc_dis = ACCEPT;
2863
30
                lexer->state = GROUND_STATE;
2864
30
                break;
2865
30
            }
2866
            // yes, the top 6 bits should be zero, total 10 bits of length
2867
11.1k
            data_len = (lexer->inbuffer[idx + 1] << 8) |
2868
11.1k
                       lexer->inbuffer[idx + 2];
2869
11.1k
            data_len &= 0x03ff;   // truncate below 1024, so pacify fuzzer
2870
11.1k
            if (idx + data_len + 6 > inbuflen) {
2871
1.84k
                GPSD_LOG(LOG_WARN, &lexer->errout,
2872
1.84k
                         "RTCM3 short buffer: idx %u data_len %u inbuflen %u, "
2873
1.84k
                         "dropping.\n", idx, data_len, inbuflen);
2874
1.84k
                packet_type = BAD_PACKET;
2875
1.84k
                acc_dis = ACCEPT;
2876
1.84k
                lexer->state = GROUND_STATE;
2877
1.84k
                break;
2878
1.84k
            }
2879
9.26k
            if (LOG_IO <= lexer->errout.debug) {
2880
0
                char outbuf[BUFSIZ];
2881
                // 12 bits of message type
2882
0
                pkt_id = (lexer->inbuffer[idx + 3] << 4) |
2883
0
                         (lexer->inbuffer[idx + 4] >> 4);
2884
2885
                // print the inbuffer packet, +3 to peek ahead. (maybe)
2886
0
                GPSD_LOG(LOG_IO, &lexer->errout,
2887
0
                         "RTCM3 data_len %u type %u idx %u inbufflen %u "
2888
0
                         " buf %s\n",
2889
0
                         data_len, pkt_id, idx, inbuflen,
2890
0
                         gps_hexdump(outbuf, sizeof(outbuf),
2891
0
                                     &lexer->inbuffer[idx], data_len + 6 + 3));
2892
0
            }
2893
2894
            // The CRC includes the preamble, and data.
2895
9.26k
            if (crc24q_check(&lexer->inbuffer[idx], data_len + 6)) {
2896
2.95k
                packet_type = RTCM3_PACKET;
2897
6.31k
            } else {
2898
6.31k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2899
6.31k
                         "RTCM3 data crc failure, "
2900
6.31k
                         "%0x against %02x %02x %02x\n",
2901
6.31k
                         crc24q_hash(&lexer->inbuffer[idx], data_len + 3),
2902
6.31k
                         lexer->inbufptr[idx + data_len + 1],
2903
6.31k
                         lexer->inbufptr[idx + data_len + 2],
2904
6.31k
                         lexer->inbufptr[idx + data_len + 3]);
2905
6.31k
                packet_type = BAD_PACKET;
2906
6.31k
            }
2907
9.26k
            acc_dis = ACCEPT;
2908
9.26k
            lexer->state = GROUND_STATE;
2909
9.26k
            break;
2910
2911
0
#ifdef SIRF_ENABLE
2912
15.2k
        case SIRF_RECOGNIZED:
2913
15.2k
            {
2914
15.2k
                unsigned char *trailer;
2915
15.2k
                trailer = lexer->inbufptr - 4;
2916
2917
15.2k
                crc_expected = (trailer[0] << 8) | trailer[1];
2918
15.2k
                crc_computed = 0;
2919
2920
282k
                for (idx = 4; idx < (inbuflen - 4); idx++) {
2921
267k
                    crc_computed += lexer->inbuffer[idx];
2922
267k
                }
2923
15.2k
                crc_computed &= 0x7fff;
2924
15.2k
                if (crc_expected == crc_computed) {
2925
13.2k
                    packet_type = SIRF_PACKET;
2926
13.2k
                    acc_dis = ACCEPT;
2927
13.2k
                } else {
2928
2.01k
                    packet_type = BAD_PACKET;
2929
2.01k
                    acc_dis = ACCEPT;
2930
2.01k
                    lexer->state = GROUND_STATE;
2931
2.01k
                }
2932
15.2k
            }
2933
15.2k
            break;
2934
0
#endif  // SIRF_ENABLE
2935
2936
0
        case SPARTN_RECOGNIZED:
2937
0
            packet_type = SPARTN_PACKET;
2938
0
            lexer->state = GROUND_STATE;
2939
0
            acc_dis = ACCEPT;
2940
0
            break;
2941
0
#ifdef SKYTRAQ_ENABLE
2942
18.0k
        case SKY_RECOGNIZED:
2943
18.0k
            packet_type = SKY_PACKET;
2944
18.0k
            acc_dis = ACCEPT;
2945
18.0k
            break;
2946
0
#endif  // SKYTRAQ_ENABLE
2947
2948
0
#ifdef STASH_ENABLE
2949
17.9k
        case STASH_RECOGNIZED:
2950
17.9k
            packet_stash(lexer);
2951
17.9k
            packet_discard(lexer);
2952
17.9k
            break;
2953
0
#endif  // STASH_ENABLE
2954
2955
0
#ifdef SUPERSTAR2_ENABLE
2956
9.60k
        case SUPERSTAR2_RECOGNIZED:
2957
2958
9.60k
            crc_computed = 0;
2959
9.60k
            lexer->length = 4 + (size_t)lexer->inbuffer[3] + 2;
2960
9.60k
            if (261 < lexer->length) {
2961
                // can't happen, pacify coverity by checking anyway.
2962
0
                lexer->length = 261;
2963
0
            }
2964
428k
            for (idx = 0; idx < lexer->length - 2; idx++) {
2965
419k
                crc_computed += lexer->inbuffer[idx];
2966
419k
            }
2967
9.60k
            crc_expected = getleu16(lexer->inbuffer, lexer->length - 2);
2968
9.60k
            GPSD_LOG(LOG_IO, &lexer->errout,
2969
9.60k
                     "SuperStarII pkt dump: type %u len %zu\n",
2970
9.60k
                     lexer->inbuffer[1], lexer->length);
2971
9.60k
            if (crc_expected != crc_computed) {
2972
5.55k
                GPSD_LOG(LOG_PROG, &lexer->errout,
2973
5.55k
                         "REJECT SuperStarII packet type 0x%02x"
2974
5.55k
                         "%zd bad checksum 0x%04x, expecting 0x%04x\n",
2975
5.55k
                         lexer->inbuffer[1], lexer->length,
2976
5.55k
                         crc_computed, crc_expected);
2977
5.55k
                packet_type = BAD_PACKET;
2978
5.55k
                lexer->state = GROUND_STATE;
2979
5.55k
            } else {
2980
4.04k
                packet_type = SUPERSTAR2_PACKET;
2981
4.04k
            }
2982
9.60k
            acc_dis = ACCEPT;
2983
9.60k
            break;
2984
0
#endif  // SUPERSTAR2_ENABLE
2985
2986
0
#if defined(TSIP_ENABLE) || defined(GARMIN_ENABLE)
2987
101k
        case TSIP_RECOGNIZED:
2988
            /* Could be Garmin, or TSIP.  Both are DLE stuffed.
2989
             *
2990
             * Garmin: DLE, ID, Length, data..., checksum, DLE, ETX
2991
             * TSIP: DLE, ID, data..., DLE, ETX
2992
             *
2993
             * Note: TSIP has no length, or checksum.  Shame!
2994
             * So we check for Garmin length and checksum, if they
2995
             * fail, we check for TSIP ID's, maybe their matching lengths.
2996
             */
2997
2998
            // Assume bad
2999
101k
            packet_type = BAD_PACKET;
3000
101k
            lexer->state = GROUND_STATE;
3001
101k
            acc_dis = ACCEPT;
3002
3003
101k
            do {
3004
101k
                int dlecnt;
3005
3006
                // don't count stuffed DLEs in the length
3007
101k
                dlecnt = 0;
3008
3.52M
                for (idx = 0; idx < inbuflen; idx++) {
3009
3.42M
                    if (DLE == lexer->inbuffer[idx]) {
3010
297k
                        dlecnt++;
3011
297k
                    }
3012
3.42M
                }
3013
101k
                if (dlecnt > 2) {
3014
8.08k
                    dlecnt -= 2;
3015
8.08k
                    dlecnt /= 2;
3016
8.08k
                    GPSD_LOG(LOG_RAW1, &lexer->errout,
3017
8.08k
                             "Unstuffed %d DLEs\n", dlecnt);
3018
8.08k
                    inbuflen -= dlecnt;
3019
8.08k
                }
3020
3021
101k
                if (5 > inbuflen) {
3022
                    // Message has no data.  Can't be GARMIN or TSIP.
3023
1.94k
                    break;
3024
1.94k
                }
3025
99.4k
#ifdef GARMIN_ENABLE
3026
99.4k
                do {
3027
99.4k
#ifdef TSIP_ENABLE
3028
                    // last packet was TSIP, shortcut garmin
3029
99.4k
                    if (TSIP_PACKET == lexer->type) {
3030
48.1k
                        break;
3031
48.1k
                    }
3032
51.3k
#endif  // TSIP_ENABLE
3033
                    // We know DLE == lexer->inbuffer[0]
3034
51.3k
                    idx = 1;
3035
3036
                    // Garmin promises ID's 3 (ETX) and 16 (DLE) are never used
3037
51.3k
                    pkt_id = lexer->inbuffer[idx++];  // packet ID, byte 1.
3038
3039
                    // Get data length from packet.
3040
51.3k
                    data_len = lexer->inbuffer[idx++];
3041
51.3k
                    crc_computed = data_len + pkt_id;
3042
51.3k
                    if (DLE == data_len &&
3043
3.90k
                        DLE != lexer->inbuffer[idx++]) {
3044
                        // Bad DLE stuffing
3045
2.73k
                        break;
3046
2.73k
                    }
3047
                    // Compute checksum.
3048
48.6k
                    data_len++;
3049
660k
                    for (; data_len > 0; data_len--) {
3050
648k
                        crc_computed += lexer->inbuffer[idx];
3051
648k
                        if (DLE == lexer->inbuffer[idx++] &&
3052
42.3k
                            DLE != lexer->inbuffer[idx++]) {
3053
                            // Bad DLE stuffing
3054
36.2k
                            break;
3055
36.2k
                        }
3056
648k
                    }
3057
3058
48.6k
                    crc_computed &= 0xff;
3059
48.6k
                    if (0 != crc_computed) {
3060
42.9k
                        GPSD_LOG(LOG_PROG, &lexer->errout,
3061
42.9k
                                 "Garmin checksum failed: %02x!=0\n",
3062
42.9k
                                 crc_computed);
3063
42.9k
                        break;
3064
42.9k
                    }
3065
3066
                    // Check for trailer where expected
3067
5.67k
                    if (DLE != lexer->inbuffer[idx++] ||
3068
5.13k
                        ETX != lexer->inbuffer[idx]) {
3069
                        // we used to say idx++ here, but scan-build complains
3070
1.24k
                        break;
3071
1.24k
                    }
3072
3073
                    // A good packet!
3074
4.42k
                    packet_type = GARMIN_PACKET;
3075
4.42k
                    break;    // redundant...
3076
5.67k
                } while (0);
3077
3078
99.4k
                if (GARMIN_PACKET == packet_type) {
3079
4.42k
                    break;
3080
4.42k
                }
3081
95.0k
                GPSD_LOG(LOG_RAW1, &lexer->errout, "Not a Garmin packet\n");
3082
                // Could be TSIP, but line noise can look like TSIP.
3083
3084
95.0k
#endif  // GARMIN_ENABLE
3085
95.0k
#ifdef TSIP_ENABLE
3086
95.0k
                do {
3087
                    /* Since TSIP has no length, or checksum,
3088
                     * check for some common TSIP packet types:
3089
                     * 0x13, TSIP Parsing Error Notification
3090
                     * 0x1c, Hardware/Software Version Information
3091
                     * 0x38, Request SV system data
3092
                     * 0x40, Almanac
3093
                     * 0x41, GPS time, data length 10
3094
                     * 0x42, Single Precision Fix XYZ, data length 16
3095
                     * 0x43, Velocity Fix XYZ, ECEF, data length 20
3096
                     * 0x45, Software Version Information, data length 10
3097
                     * 0x46, Health of Receiver, data length 2
3098
                     * 0x47, Signal Level all Sats Tracked, data length 1+5*numSV
3099
                     * 0x48, GPS System Messages, data length 22
3100
                     * 0x49, Almanac Health Page, data length 32
3101
                     * 0x4a, Single Precision Fix LLA, data length 20
3102
                     * 0x4b, Machine Code Status, data length 3
3103
                     * 0x4c, Operating Parameters Report, data length 17
3104
                     * 0x4d, Oscillator Offset
3105
                     * 0x4e, Response to set GPS time
3106
                     * 0x54, One Satellite Bias, data length 12
3107
                     * 0x55, I/O Options, data length 4
3108
                     * 0x56, Velocity Fix ENU, data length 20
3109
                     * 0x57, Last Computed Fix Report, data length 8
3110
                     * 0x58, Satellite System Data
3111
                     * 0x58-05, UTC
3112
                     * 0x59, Satellite Health
3113
                     * 0x5a, Raw Measurements
3114
                     * 0x5b, Satellite Ephemeris Status, data length 16
3115
                     * 0x5c, Satellite Tracking Status, data length 24
3116
                     * 0x5d, Satellite Tracking Stat, multi-gnss, data length 26
3117
                     * 0x5e, Additional Fix Status Report
3118
                     * 0x5f, Severe Failure Notification
3119
                     * 0x5F-01-0B: Reset Error Codes
3120
                     * 0x5F-02: Ascii text message
3121
                     * 0x6c, Satellite Selection List, data length 18+numSV
3122
                     * 0x6d, All-In-View Satellites, data length 17+numSV
3123
                     * 0x6f, Synced Measurement Packet
3124
                     * 0x72, PV filter parameters
3125
                     * 0x74, Altitude filter parameters
3126
                     * 0x78, Max DGPS correction age
3127
                     * 0x7b, NMEA message schedule
3128
                     * 0x82, Differential Position Fix Mode, data length 1
3129
                     * 0x83, Double Precision Fix XYZ, data length 36
3130
                     * 0x84, Double Precision Fix LLA, data length 36
3131
                     * 0x85, DGPS Correction status
3132
                     * 0x8f, Superpackets
3133
                     * 0x8f-01,
3134
                     * 0x8f-02,
3135
                     * 0x8f-03, port configuration
3136
                     * 0x8f-14, datum
3137
                     * 0x8f-15, datum
3138
                     * 0x8f-17, Single Precision UTM
3139
                     * 0x8f-18, Double Precision UTM
3140
                     * 0x8f-20, LLA & ENU
3141
                     * 0x8f-26, SEEPROM write status
3142
                     * 0x8f-40, TAIP Configuration
3143
                     * 0x8f-42, Stored Production Parameters
3144
                     * 0x90-XX, Version/Config (TSIPv1)
3145
                     * 0xa1-00, Timing Info (TSIPv1)
3146
                     * 0xa1-01, Frequency Info (TSIPv1)
3147
                     * 0xa1-02, Position Info (TSIPv1)
3148
                     * 0xbb, GPS Navigation Configuration
3149
                     * 0xbc, Receiver Port Configuration
3150
                     *
3151
                     * <DLE>[pkt id] [data] <DLE><ETX>
3152
                     *
3153
                     * The best description is in [TSIP], the Trimble Standard
3154
                     * Interface Protocol manual; unless otherwise specified
3155
                     * that is where these type/length notifications are from.
3156
                     *
3157
                     * Note that not all Trimble chips conform perfectly to this
3158
                     * specification, nor does it cover every packet type we
3159
                     * may see on the wire.
3160
                     */
3161
95.0k
                    pkt_id = lexer->inbuffer[1];    // packet ID
3162
                    // *INDENT-OFF*
3163
                    // FIXME: combine this if, and the next ones?
3164
95.0k
                    if (!((0x13 == pkt_id) ||
3165
93.5k
                          (0x1c == pkt_id) ||
3166
88.9k
                          (0x38 == pkt_id) ||
3167
88.5k
                          ((0x41 <= pkt_id) && (0x4c >= pkt_id)) ||
3168
66.5k
                          ((0x54 <= pkt_id) && (0x57 >= pkt_id)) ||
3169
57.4k
                          ((0x5a <= pkt_id) && (0x5f >= pkt_id)) ||
3170
46.5k
                          (0x6c == pkt_id) ||
3171
43.3k
                          (0x6d == pkt_id) ||
3172
39.9k
                          (0x82 <= pkt_id &&
3173
32.2k
                           0x84 >= pkt_id) ||
3174
34.9k
                          (0x8f <= pkt_id &&
3175
26.7k
                           0x93 >= pkt_id) ||
3176
18.9k
                          (0xbb == pkt_id) ||
3177
17.6k
                          (0xbc == pkt_id) ||
3178
17.1k
                          ((0xa1 <= pkt_id &&
3179
12.8k
                           0xa3 >= pkt_id)))) {
3180
12.8k
                        GPSD_LOG(LOG_PROG, &lexer->errout,
3181
12.8k
                                 "Packet ID 0x%02x out of range for TSIP\n",
3182
12.8k
                                 pkt_id);
3183
12.8k
                        break;
3184
12.8k
                    }
3185
                    // *INDENT-ON*
3186
1.43M
#define TSIP_ID_AND_LENGTH(id, len)     ((id == pkt_id) && \
3187
1.43M
                                         (len == (inbuflen - 4)))
3188
3189
82.2k
                    if (0x13 == pkt_id) {
3190
1.48k
                        ;  // pass
3191
                        /*
3192
                         * Not in [TSIP],  Accutime Gold only. Variable length.
3193
                         */
3194
80.7k
                    } else if ((0x1c == pkt_id) &&
3195
4.60k
                               (11 <= inbuflen)) {
3196
4.11k
                        ;  // pass
3197
76.6k
                    } else if (TSIP_ID_AND_LENGTH(0x41, 10)) {
3198
852
                        ;  // pass
3199
75.8k
                    } else if (TSIP_ID_AND_LENGTH(0x42, 16)) {
3200
2.45k
                        ;  // pass
3201
73.3k
                    } else if (TSIP_ID_AND_LENGTH(0x43, 20)) {
3202
1.27k
                        ;  // pass
3203
72.0k
                    } else if (TSIP_ID_AND_LENGTH(0x45, 10)) {
3204
486
                        ;  // pass
3205
71.5k
                    } else if (TSIP_ID_AND_LENGTH(0x46, 2)) {
3206
2.71k
                        ;  // pass
3207
68.8k
                    } else if ((0x47 == pkt_id) &&
3208
1.63k
                               (0 == (inbuflen % 5))) {
3209
                        /*
3210
                         * 0x47 data length 1+5*numSV, packetlen is 5+5*numSV
3211
                         * FIXME, should be a proper length calculation
3212
                         */
3213
1.05k
                         ;  // pass
3214
67.8k
                    } else if (TSIP_ID_AND_LENGTH(0x48, 22)) {
3215
288
                        ;  // pass
3216
67.5k
                    } else if (TSIP_ID_AND_LENGTH(0x49, 32)) {
3217
295
                        ;  // pass
3218
67.2k
                    } else if (TSIP_ID_AND_LENGTH(0x4a, 20)) {
3219
1.63k
                        ;  // pass
3220
65.5k
                    } else if (TSIP_ID_AND_LENGTH(0x4b, 3)) {
3221
2.47k
                        ;  // pass
3222
63.1k
                    } else if (TSIP_ID_AND_LENGTH(0x4c, 17)) {
3223
448
                        ;  // pass
3224
62.6k
                    } else if (TSIP_ID_AND_LENGTH(0x54, 12)) {
3225
1.84k
                        ;  // pass
3226
60.8k
                    } else if (TSIP_ID_AND_LENGTH(0x55, 4)) {
3227
1.52k
                        ;  // pass
3228
59.3k
                    } else if (TSIP_ID_AND_LENGTH(0x56, 20)) {
3229
1.19k
                        ;  // pass
3230
58.1k
                    } else if (TSIP_ID_AND_LENGTH(0x57, 8)) {
3231
1.67k
                        ;  // pass
3232
56.4k
                    } else if (TSIP_ID_AND_LENGTH(0x5a, 25)) {
3233
359
                        ;  // pass
3234
56.0k
                    } else if (TSIP_ID_AND_LENGTH(0x5b, 16)) {
3235
332
                        ;  // pass
3236
55.7k
                    } else if (TSIP_ID_AND_LENGTH(0x5c, 24)) {
3237
2.47k
                        ;  // pass
3238
53.2k
                    } else if (TSIP_ID_AND_LENGTH(0x5d, 26)) {
3239
3.28k
                        ;  // pass
3240
49.9k
                    } else if (TSIP_ID_AND_LENGTH(0x5e, 2)) {
3241
588
                        ;  // pass
3242
                     /*
3243
                     * Not in [TSIP]. the TSIP driver doesn't use type 0x5f.
3244
                     * but we test for it so as to avoid setting packet not_tsip
3245
                     */
3246
49.3k
                    } else if (TSIP_ID_AND_LENGTH(0x5f, 66)) {
3247
                        /*
3248
                         * 0x6c data length 18+numSV, total packetlen is 22+numSV
3249
                         * numSV up to 224
3250
                         */
3251
213
                        ;  // pass
3252
49.1k
                    } else if ((0x6c == pkt_id) &&
3253
3.20k
                               ((22 <= inbuflen) &&
3254
2.38k
                                (246 >= inbuflen))) {
3255
                        /*
3256
                         * 0x6d data length 17+numSV, total packetlen is 21+numSV
3257
                         * numSV up to 32
3258
                         */
3259
2.23k
                        ;  // pass
3260
46.9k
                    } else if ((0x6d == pkt_id) &&
3261
3.40k
                               ((21 <= inbuflen) &&
3262
2.86k
                                (53 >= inbuflen))) {
3263
2.45k
                        ;  // pass
3264
44.4k
                    } else if (TSIP_ID_AND_LENGTH(0x82, 1)) {
3265
834
                        ;  // pass
3266
43.6k
                    } else if (TSIP_ID_AND_LENGTH(0x83, 36)) {
3267
1.16k
                        ;  // pass
3268
42.5k
                    } else if (TSIP_ID_AND_LENGTH(0x84, 36)) {
3269
                        // pass
3270
41.4k
                    } else if (0x8f <= pkt_id &&
3271
22.1k
                               0x93 >= pkt_id) {
3272
                        // pass, TSIP super packets, variable length
3273
                        // pass, TSIPv1 version/config/info super packet
3274
25.4k
                    } else if (0xa0 <= pkt_id &&
3275
6.11k
                               0xa3 >= pkt_id) {
3276
                        // PASS, TSIPv1
3277
                        // FIXME: check for sub packet id 0 to 2
3278
                    /*
3279
                     * This is according to [TSIP].
3280
                     */
3281
21.0k
                    } else if (TSIP_ID_AND_LENGTH(0xbb, 40)) {
3282
302
                        ;  // pass
3283
                    /*
3284
                     * The Accutime Gold ships a version of this packet with a
3285
                     * 43-byte payload.  We only use the first 21 bytes, and
3286
                     * parts after byte 27 are padding.
3287
                     */
3288
20.7k
                    } else if (TSIP_ID_AND_LENGTH(0xbb, 43)) {
3289
344
                        ;  // pass
3290
20.3k
                    } else {
3291
20.3k
                        ;  // pass
3292
20.3k
                        GPSD_LOG(LOG_PROG, &lexer->errout,
3293
20.3k
                                 "TSIP REJECT pkt_id = %#02x, inbuflen= %d\n",
3294
20.3k
                                 pkt_id, inbuflen);
3295
20.3k
                        break;
3296
20.3k
                    }
3297
61.8k
#undef TSIP_ID_AND_LENGTH
3298
                    // Debug
3299
61.8k
                    GPSD_LOG(LOG_RAW, &lexer->errout,
3300
61.8k
                             "TSIP pkt_id = %#02x, inbuflen= %d\n",
3301
61.8k
                             pkt_id, inbuflen);
3302
61.8k
                    packet_type = TSIP_PACKET;
3303
61.8k
                    lexer->state = TSIP_RECOGNIZED;
3304
61.8k
                    break;     // redundant
3305
82.2k
                } while (0);
3306
3307
95.0k
                if (BAD_PACKET == packet_type) {
3308
33.2k
                    GPSD_LOG(LOG_RAW1, &lexer->errout, "Not a TSIP packet\n");
3309
33.2k
                    acc_dis = ACCEPT;
3310
33.2k
                    lexer->state = GROUND_STATE;
3311
33.2k
                }
3312
95.0k
                break;   // redundant
3313
99.4k
#endif  // TSIP_ENABLE
3314
99.4k
            } while (0);
3315
101k
            break;
3316
0
#endif  // TSIP_ENABLE || GARMIN_ENABLE
3317
3318
27.8k
        case UBX_RECOGNIZED:
3319
            // UBX use a TCP like checksum
3320
27.8k
            ck_a = (unsigned char)0;
3321
27.8k
            ck_b = (unsigned char)0;
3322
3323
27.8k
            GPSD_LOG(LOG_IO, &lexer->errout, "UBX: len %d\n", inbuflen);
3324
1.73M
            for (idx = 2; idx < (inbuflen - 2); idx++) {
3325
1.70M
                ck_a += lexer->inbuffer[idx];
3326
1.70M
                ck_b += ck_a;
3327
1.70M
            }
3328
27.8k
            if (ck_a == lexer->inbuffer[inbuflen - 2] &&
3329
22.1k
                ck_b == lexer->inbuffer[inbuflen - 1]) {
3330
20.8k
                packet_type = UBX_PACKET;
3331
20.8k
            } else {
3332
6.95k
                GPSD_LOG(LOG_PROG, &lexer->errout,
3333
6.95k
                         "UBX checksum 0x%02hhx%02hhx over length %d,"
3334
6.95k
                         " expecting 0x%02hhx%02hhx (type 0x%02hhx%02hhx)\n",
3335
6.95k
                         ck_a,
3336
6.95k
                         ck_b,
3337
6.95k
                         inbuflen,
3338
6.95k
                         lexer->inbuffer[inbuflen - 2],
3339
6.95k
                         lexer->inbuffer[inbuflen - 1],
3340
6.95k
                         lexer->inbuffer[2], lexer->inbuffer[3]);
3341
6.95k
                packet_type = BAD_PACKET;
3342
6.95k
                lexer->state = GROUND_STATE;
3343
6.95k
            }
3344
27.8k
            acc_dis = ACCEPT;
3345
27.8k
            break;
3346
3347
0
#ifdef ZODIAC_ENABLE
3348
2.46k
        case ZODIAC_RECOGNIZED:
3349
            // be paranoid, look ahead for a good checksum
3350
2.46k
            data_len = getzuword(2);
3351
2.46k
            if (253 < data_len) {
3352
                // pacify coverity, 253 seems to be max length
3353
415
                data_len = 253;
3354
415
            }
3355
2.46k
            crc_computed = 0;
3356
119k
            for (idx = 0; idx < data_len; idx++) {
3357
116k
                crc_computed += getzword(5 + idx);
3358
116k
            }
3359
2.46k
            crc_expected = getzword(5 + data_len);
3360
2.46k
            crc_computed += crc_expected;
3361
2.46k
            crc_computed &= 0x0ff;
3362
2.46k
            if (0 == data_len ||
3363
1.72k
                0 == crc_computed) {
3364
1.72k
                packet_type = ZODIAC_PACKET;
3365
1.72k
            } else {
3366
737
                GPSD_LOG(LOG_PROG, &lexer->errout,
3367
737
                         "Zodiac data checksum 0x%x over length %u, "
3368
737
                         "expecting 0x%x\n",
3369
737
                         crc_expected, data_len, getzword(5 + data_len));
3370
737
                packet_type = BAD_PACKET;
3371
737
                lexer->state = GROUND_STATE;
3372
737
            }
3373
2.46k
            acc_dis = ACCEPT;
3374
2.46k
            break;
3375
451M
#endif  // ZODIAC_ENABLE
3376
3377
451M
        }
3378
451M
        if (ACCEPT == acc_dis) {
3379
462k
            packet_accept(lexer, packet_type);
3380
462k
            packet_discard(lexer);
3381
462k
#ifdef STASH_ENABLE
3382
462k
            if (unstash &&
3383
74.6k
                0 != lexer->stashbuflen) {
3384
7.65k
                packet_unstash(lexer);
3385
7.65k
            }
3386
462k
#endif  // STASH_ENABLE
3387
462k
            break;
3388
462k
        }
3389
451M
    }                           // while
3390
498k
}
3391
3392
/* packet_get() -- deprecated 2023, use packet_get1() instead
3393
 * exposed in Python FFI.
3394
 */
3395
ssize_t packet_get(int fd, struct gps_lexer_t *lexer)
3396
56.0k
{
3397
56.0k
    struct gps_device_t session = {{0}};
3398
56.0k
    ssize_t retval;
3399
56.0k
    ssize_t inbufptrcnt = lexer->inbufptr - lexer->inbuffer;
3400
3401
56.0k
    session.gpsdata.gps_fd = fd;
3402
56.0k
    session.lexer = *lexer;   // structure copy
3403
3404
    // fix inbufptr
3405
56.0k
    session.lexer.inbufptr = session.lexer.inbuffer + inbufptrcnt;
3406
3407
56.0k
    retval = packet_get1(&session);
3408
3409
56.0k
    *lexer = session.lexer;   // structure copy
3410
3411
    // fix inbufptr
3412
56.0k
    inbufptrcnt = session.lexer.inbufptr - session.lexer.inbuffer;
3413
56.0k
    lexer->inbufptr = lexer->inbuffer + inbufptrcnt;
3414
3415
56.0k
    return retval;
3416
56.0k
}
3417
3418
3419
/* packet_get1_chunked() - grab an http/1.1 chunked packet;
3420
 *
3421
 * Handle http/1.1 chunking as a layer above the packet layer.
3422
 * so far only NTRIP v2 uses it.  Perversely the chunks do
3423
 * not seem to align with received packets.
3424
 *
3425
 * A pointless feature in http/1.1
3426
 *
3427
 * return: greater than zero: length
3428
 *         > 0  == got a packet.
3429
 *         0 == EOF or no full packet
3430
 *        -1 == I/O error
3431
 */
3432
static ssize_t packet_get1_chunked(struct gps_device_t *session)
3433
0
{
3434
0
    ssize_t recvd;
3435
0
    char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
3436
    // (int) to pacify Codacy
3437
0
    int fd = (int)session->gpsdata.gps_fd;
3438
0
    struct gps_lexer_t *lexer = &session->lexer;
3439
0
    size_t idx = 0;                 // index into inbuffer.
3440
0
    unsigned char *tmp_bufptr;      // pointer to head in tmp_buffer
3441
0
    ssize_t taken;
3442
    // make tmp_buffer large, to simplify overflow prevention
3443
0
    unsigned char tmp_buffer[sizeof(lexer->inbuffer) * 2];
3444
3445
0
    GPSD_LOG(LOG_PROG, &lexer->errout,
3446
0
             "PACKET: packet_get1_chunked(fd %d) enter inbuflen %zu "
3447
0
             "offset %d remaining %d\n",
3448
0
             fd, lexer->inbuflen, (int) (lexer->inbufptr - lexer->inbuffer),
3449
0
             lexer->chunk_remaining);
3450
3451
0
    if (sizeof(lexer->inbuffer) < lexer->inbuflen) {
3452
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3453
0
                 "PACKET: packet_get1_chunked(fd %d) start inbuflen %zu "
3454
0
                 "< 0 !!!\n",
3455
0
                 fd, lexer->inbuflen);
3456
0
        return -1;  // unrecoverable error
3457
0
    }
3458
3459
0
    errno = 0;
3460
0
    recvd = 0;
3461
0
    if (2048 > lexer->inbuflen) {
3462
        /* Do not bother to read if we already have enough for longest
3463
         * RTCM3 message.  Longest RTCM3 message is 1023 plus header
3464
         * and chunk overhead.
3465
         * O_NONBLOCK set, so this should not block.
3466
         * Best not to block on an unresponsive NTRIP server.
3467
         * They tend to be bursty.  Like 18kb, then nothing for many
3468
         * seconds. */
3469
0
        recvd = read(fd, lexer->inbuffer + lexer->inbuflen,
3470
0
                     sizeof(lexer->inbuffer) - lexer->inbuflen);
3471
0
    } else {
3472
0
        GPSD_LOG(LOG_IO, &lexer->errout,
3473
0
                 "PACKET: packet_get1_chunked(fd %d) got enough inbuflen %zu "
3474
0
                 "offset %d\n",
3475
0
                 fd, lexer->inbuflen,
3476
0
                 (int) (lexer->inbufptr - lexer->inbuffer));
3477
0
    }
3478
3479
0
    if (0 == recvd &&
3480
0
        0 == lexer->inbuflen) {
3481
        /* When reading from a TCP socket, and no bytes ready, read()
3482
         * returns 0 and sets errno to 11 (Resource temporarily unavailable).
3483
         */
3484
0
        if (EAGAIN != errno) {
3485
0
            GPSD_LOG(LOG_WARN, &lexer->errout,
3486
0
                     "PACKET: packet_get1_chunked(fd %d) recvd %zd %s(%d)\n",
3487
0
                     fd, recvd, strerror(errno), errno);
3488
0
            return -1;   // unrecoverable error.
3489
0
        } // else
3490
0
        GPSD_LOG(LOG_RAW2, &lexer->errout,
3491
0
                 "PACKET: packet_get1_chunked(fd %d)  no bytes ready\n",
3492
0
                 fd);
3493
0
        return 1;  // pretend we got something, to keep connection open
3494
0
    } // else
3495
3496
0
    if (0 > recvd) {
3497
0
        if (EAGAIN == errno ||
3498
0
            EINTR == errno) {
3499
0
            GPSD_LOG(LOG_RAW2, &lexer->errout, "PACKET: no bytes ready\n");
3500
0
            recvd = 0;
3501
            // No new bytes, maybe already have enough bytes for a message
3502
0
        } else {
3503
0
            GPSD_LOG(LOG_WARN, &lexer->errout,
3504
0
                     "PACKET: packet_get1_chunked(fd %d) errno: %s(%d)\n",
3505
0
                     fd, strerror(errno), errno);
3506
0
            return -1;   // unrecoverable error.
3507
0
        }
3508
0
    }  // else
3509
3510
    // Got some data.
3511
0
    lexer->inbuflen += recvd;
3512
3513
0
    GPSD_LOG(LOG_IO, &lexer->errout,
3514
0
             "PACKET: packet_get1_chunked(fd %d) recvd %zd inbuflen %zd "
3515
0
             "mid remaining %d >%.100s<\n",
3516
0
             fd, recvd, lexer->inbuflen, lexer->chunk_remaining,
3517
0
             gps_hexdump(scratchbuf, sizeof(scratchbuf),
3518
0
                         lexer->inbufptr, lexer->inbuflen));
3519
3520
    /* Preversly, the buffer may be just 4 bytes.
3521
     * Some servers send just 0x36340d0a in one packet
3522
     * smallest valid chunk: "0\r\n\r\n"
3523
     * Give up for now */
3524
0
    if (5 >= lexer->inbuflen) {
3525
0
        GPSD_LOG(LOG_IO, &lexer->errout,
3526
0
                 "PACKET: packet_get1_chunked(fd %d) < 5 remaining %d\n",
3527
0
                 fd, lexer->chunk_remaining);
3528
0
        return 0;       // got nothing.
3529
0
    }
3530
    /* The length in the header may be up to 1023, plus message
3531
     * overhead.
3532
     * Here we may have N remaining at the head of inbuffer, followed
3533
     * by part, or all, of the next bit to unchunk.*/
3534
0
    if (0 > lexer->chunk_remaining) {
3535
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3536
0
                 "PACKET: packet_get1_chunkedfd %d) remaining %d < 0 !!!\n",
3537
0
                 fd, lexer->chunk_remaining);
3538
0
        return -1;   // unrecoverable error.
3539
0
    }
3540
0
    if (lexer->inbuflen > (long unsigned)lexer->chunk_remaining) {
3541
        // need unchunking
3542
0
        size_t tmp_buflen = lexer->inbuflen - lexer->chunk_remaining;
3543
0
        int chunk_num;            // many chunks in one buffer,
3544
3545
        /* Make a copy of the unchunked part of inbuffer.
3546
         * Then unchunk it back into inbuffer. */
3547
0
        lexer->inbufptr = &lexer->inbuffer[lexer->chunk_remaining];
3548
0
        memset(tmp_buffer, 0, sizeof(tmp_buffer));
3549
0
        memmove(tmp_buffer, lexer->inbufptr, tmp_buflen);
3550
3551
        // get ready to copy chunks back into the inbuffer
3552
0
        tmp_bufptr = tmp_buffer;
3553
0
        lexer->inbuflen = lexer->chunk_remaining;
3554
3555
0
        for (chunk_num = 0; ; chunk_num++) {
3556
0
            size_t needed = 0;
3557
0
            int chunk_size = 0;        // given chunk size
3558
0
            long chunk_size_l = 0;     // given chunk size, as a long
3559
0
            unsigned char *endptr;     // for strtol()
3560
3561
            // get the hexadecimal chunk size.
3562
0
            chunk_size_l = strtol((char *)tmp_bufptr, (char **)&endptr, 16);
3563
0
            if (0 > chunk_size_l ||
3564
0
                10000 < chunk_size_l) {
3565
                // don't let chunk be negative, or too large.
3566
0
                GPSD_LOG(LOG_ERROR, &lexer->errout,
3567
0
                         "PACKET: packet_get1_chunkedfd %d) invalid  "
3568
0
                         "chunk_size %ld!!!\n",
3569
0
                         fd, chunk_size_l);
3570
0
                return -1;   // unrecoverable error.
3571
0
            }
3572
0
            chunk_size = chunk_size_l;  // We already tested it fits.
3573
3574
0
            GPSD_LOG(LOG_IO, &lexer->errout,
3575
0
                     "PACKET: packet_get1_chunkedfd %d) doing chunk %d  "
3576
0
                     "size %d inbuflen %zu >%.200s<\n",
3577
0
                     fd, chunk_num, chunk_size, lexer->inbuflen,
3578
0
                     gps_hexdump(scratchbuf, sizeof(scratchbuf),
3579
0
                                 tmp_bufptr, tmp_buflen));
3580
3581
0
            idx = endptr - tmp_bufptr;
3582
3583
            // check for valid hex ending
3584
            // need better test for overrun
3585
0
            if (';' != *endptr &&
3586
0
                '\r' != *endptr) {
3587
                // invalid ending.  valid endings are ':' or '\r\n' (0d0a).
3588
0
                GPSD_LOG(LOG_WARN, &lexer->errout,
3589
0
                         "PACKET: NTRIP: packet_get1_chunked(fd %d) "
3590
0
                         "invalid ending idx %zu (x%x).\n",
3591
0
                         fd, idx, *endptr);
3592
                // unrecoverable?
3593
0
                break;   // assume we need more input??
3594
0
            }
3595
0
            idx++;   // skip past the ":" or "\r"
3596
3597
            // move past '\n' line ending
3598
0
            for (; tmp_bufptr[idx] < tmp_buffer[sizeof(tmp_buffer) - 1];
3599
0
                 idx++) {
3600
0
                if ('\n' == tmp_bufptr[idx]) {
3601
0
                    break;
3602
0
                }
3603
0
            }
3604
0
            if ('\n' != tmp_bufptr[idx]) {
3605
                // Invalid ending.  The only valid ending is '\n'.
3606
0
                GPSD_LOG(LOG_IO, &lexer->errout,
3607
0
                         "PACKET: NTRIP: packet_get1_chunked(fd %d) "
3608
0
                         "invalid ending 2, idx %zu x%02x\n",
3609
0
                         fd, idx, tmp_bufptr[idx]);
3610
0
                break;   // assume we need more input.
3611
0
            }
3612
0
            idx++;    // move past the trailing '\n'
3613
3614
            /* to unchunk we need chunk size + 2 more for \r\n + 2 more
3615
             * for the tailing \r\n */
3616
0
            needed = chunk_size + 2 + idx;
3617
0
            GPSD_LOG(LOG_IO, &lexer->errout,
3618
0
                     "PACKET: NTRIP: packet_get1_chunked(fd  %d) size %d "
3619
0
                     "idx %zu buflen %zu needed %zu %s\n",
3620
0
                     fd, chunk_size, idx, tmp_buflen, needed,
3621
0
                     gps_hexdump(scratchbuf, sizeof(scratchbuf),
3622
0
                                 tmp_bufptr, 10));
3623
0
            if (needed > tmp_buflen) {
3624
                /* Don't have enough yet.  Annoyingly, centipede can send
3625
                 * the chunk count line, but not the chunked data yet!!
3626
                 * Like this: "64\r\n".
3627
                 * Save the fragment back into inbuffer
3628
                 */
3629
0
                memcpy(lexer->inbufptr, tmp_bufptr, tmp_buflen);
3630
0
                lexer->inbuflen += tmp_buflen;
3631
0
                GPSD_LOG(LOG_IO, &lexer->errout,
3632
0
                         "PACKET: NTRIP: packet_get1_chunked(fd %d) "
3633
0
                         "chunk %d not full needed %zd tmp_buflen %zu\n",
3634
0
                         fd, chunk_num, needed, tmp_buflen);
3635
0
                break;
3636
0
            }
3637
0
            lexer->chunk_remaining += chunk_size;
3638
            /* enough data in inbuffer, starting at tmp_bufptr[idx]
3639
             * move past that chunk header. */
3640
0
            tmp_bufptr += idx;
3641
0
            tmp_buflen -= idx;
3642
0
            GPSD_LOG(LOG_IO, &lexer->errout,
3643
0
                     "PACKET: NTRIP: packet_get1_chunked(fd %d) got "
3644
0
                     "chunk %d >%s<\n",
3645
0
                     fd, chunk_num,
3646
0
                     gps_hexdump(scratchbuf, sizeof(scratchbuf),
3647
0
                                 lexer->inbufptr, chunk_size));
3648
3649
            // save the chunk into inbuffer
3650
0
            memcpy(lexer->inbufptr, tmp_bufptr, chunk_size);
3651
0
            lexer->inbuflen += chunk_size;
3652
0
            lexer->inbufptr += chunk_size;
3653
3654
            // skip past the chunk trailer (\r\n)
3655
0
            tmp_bufptr += chunk_size + 2;
3656
0
            tmp_buflen -= chunk_size + 2;
3657
0
            if (0 == tmp_buflen) {
3658
0
                break;
3659
0
            }
3660
            // smallest valid chunk: "0\r\n\r\n"
3661
0
            if (5 >= tmp_buflen) {
3662
                // left overs!, put back into inbuffer later.
3663
0
                GPSD_LOG(LOG_IO, &lexer->errout,
3664
0
                         "PACKET: NTRIP: packet_get1_chunked(fd %d) "
3665
0
                         "left over %zu inbuflen %zu\n",
3666
0
                         fd, tmp_buflen, lexer->inbuflen);
3667
0
                break;
3668
0
            }
3669
0
        }
3670
0
    } // else, inbuf already unchunked
3671
3672
0
    if (0 == lexer->inbuflen) {
3673
0
        GPSD_LOG(LOG_IO, &lexer->errout,
3674
0
                 "PACKET: NTRIP: packet_get1_chunked(fd %d) got nothing,\n",
3675
0
                  fd);
3676
0
        return 1;   // not right, close enough
3677
0
    }
3678
    // data starts at lexer->inbuffer[0]
3679
0
    if (0 > lexer->chunk_remaining) {
3680
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3681
0
                 "PACKET: packet_get1_chunkedfd %d) remaining %d < 0 !!!\n",
3682
0
                 fd, lexer->chunk_remaining);
3683
0
        return -1;  // unrecoverable error
3684
0
    }
3685
0
    GPSD_LOG(LOG_IO, &lexer->errout,
3686
0
             "PACKET: packet_get1_chunked(fd %d) inbuflen %zu remaining %d "
3687
0
             "unchunked %.200s\n",
3688
0
              fd, lexer->inbuflen, lexer->chunk_remaining,
3689
0
              gps_hexdump(scratchbuf, sizeof(scratchbuf),
3690
0
                          lexer->inbuffer, lexer->inbuflen));
3691
3692
0
    if (2 <= lexer->inbuflen) {
3693
        /* now get one message
3694
         * don't  underflow  inbuflen, or voerrun inbuffer
3695
         * RTCM3 message header not always at inbufptr[0]
3696
         */
3697
0
        for (idx = 0; idx < (lexer->inbuflen - 1); idx++) {
3698
0
            if (0xd3 == lexer->inbuffer[idx] &&
3699
0
                0 == (0xfc & lexer->inbuffer[idx + 1])) {
3700
                // Looking for 0xd3, followed by 6 zeros.
3701
0
                break;
3702
0
            }
3703
0
        }
3704
0
    }
3705
0
    if (0xd3 != lexer->inbuffer[idx]) {
3706
        // start of RTCM3 not found.
3707
0
        GPSD_LOG(LOG_IO, &lexer->errout,
3708
0
                 "PACKET: packet_get1_chunked(fd %d) RTCM3 start not "
3709
0
                 "found, idx %zu, %.200s\n",
3710
0
                  fd, idx,
3711
0
                  gps_hexdump(scratchbuf, sizeof(scratchbuf),
3712
0
                              lexer->inbuffer, lexer->inbuflen));
3713
0
        return 1;   // not right, close enough
3714
0
    }
3715
    /* Prolly should check for start of next RTCM3, to ensure we
3716
     * have all of the first one.
3717
     * packet_parse() works much better is the start (0xd3) of
3718
     * messages is at inbuffer[0]
3719
     */
3720
0
    memmove(lexer->inbuffer, &lexer->inbuffer[idx], lexer->inbuflen - idx);
3721
0
    lexer->inbufptr = lexer->inbuffer;
3722
0
    lexer->inbuflen -= idx;
3723
0
    lexer->chunk_remaining -= idx;
3724
0
    if (sizeof(lexer->inbuffer) < lexer->inbuflen) {
3725
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3726
0
                 "PACKET: packet_get1_chunked(fd %d) mid inbuflen %zu !!!  "
3727
0
                 "idx %zu \n",
3728
0
                 fd, lexer->inbuflen, idx);
3729
0
        return -1;  // unrecoverable error
3730
0
    }
3731
0
    if (0 > lexer->chunk_remaining) {
3732
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3733
0
                 "PACKET: packet_get1_chunked(fd %d) idx %zu remaining %d "
3734
0
                 "< 0 !!!\n",
3735
0
                 fd, idx, lexer->chunk_remaining);
3736
0
        return -1;  // unrecoverable error
3737
0
    }
3738
0
    lexer->outbuflen = 0;
3739
3740
0
    GPSD_LOG(LOG_IO, &lexer->errout,
3741
0
             "PACKET: NTRIP: packet_get1_chunked(fd %d) to packet_parse() "
3742
0
              "inbuflen %zu idx %zu outbuflen %zu remaining %d pbu %d "
3743
0
              ">%.200s<\n",
3744
0
              fd, lexer->inbuflen, idx, lexer->outbuflen,
3745
0
              lexer->chunk_remaining, (int) packet_buffered_input(lexer),
3746
0
              gps_hexdump(scratchbuf, sizeof(scratchbuf),
3747
0
                          lexer->inbufptr, lexer->inbuflen));
3748
0
    taken = lexer->inbuflen;
3749
0
    packet_parse(lexer);
3750
0
    taken -= lexer->inbuflen;
3751
0
    lexer->chunk_remaining -= taken;
3752
3753
0
    GPSD_LOG(LOG_IO, &lexer->errout,
3754
0
             "PACKET: packet_get1_chunked(fd %d) fm packet_parse() taken %zd "
3755
0
             "inbuflen %zd outbuflen %zd remaining %d >%.200s<\n",
3756
0
             fd, taken, lexer->inbuflen, lexer->outbuflen,
3757
0
             lexer->chunk_remaining,
3758
0
             gps_hexdump(scratchbuf, sizeof(scratchbuf),
3759
0
                         lexer->outbuffer, lexer->outbuflen));
3760
3761
0
    if (sizeof(lexer->inbuffer) < lexer->inbuflen) {
3762
0
        GPSD_LOG(LOG_ERROR, &lexer->errout,
3763
0
                 "PACKET: packet_get1_chunked(fd %d) start inbuflen %zu "
3764
0
                 "< 0 !!!\n",
3765
0
                 fd, lexer->inbuflen);
3766
0
        return -1;  // unrecoverable error
3767
0
    }
3768
0
    return (ssize_t)lexer->outbuflen;
3769
0
}
3770
3771
/* grab a packet;
3772
 * return: greater than zero: length
3773
 *         > 0  == got a packet.
3774
 *         0 == EOF or no full packet
3775
 *        -1 == I/O error
3776
 */
3777
ssize_t packet_get1(struct gps_device_t *session)
3778
4.31M
{
3779
    /* recvd, and watned  big enough to hold size_t and ssize_t
3780
     * to Pacify Coveruty 498038, and avoid signed/unsigned math */
3781
4.31M
    long long recvd;
3782
4.31M
    long long wanted;
3783
4.31M
    char scratchbuf[MAX_PACKET_LENGTH * 4 + 1];
3784
4.31M
    int fd = session->gpsdata.gps_fd;
3785
4.31M
    struct gps_lexer_t *lexer = &session->lexer;
3786
3787
4.31M
    if (true == lexer->chunked) {
3788
        // De-chunking too complicated to do unlike below.
3789
0
        return packet_get1_chunked(session);
3790
0
    }
3791
3792
4.31M
    errno = 0;
3793
4.31M
    wanted = sizeof(lexer->inbuffer) - lexer->inbuflen;
3794
4.31M
    if (0 >= wanted) {
3795
        // should never happen, pacify Coverity 498039
3796
0
        return -1;
3797
0
    }
3798
    /* O_NONBLOCK set, so this should not block.
3799
     * Best not to block on an unresponsive GNSS receiver */
3800
4.31M
    recvd = read(fd, lexer->inbuffer + lexer->inbuflen, wanted);
3801
3802
4.31M
    if (-1 >= recvd) {
3803
4.21M
        if (EAGAIN == errno ||
3804
4.21M
            EINTR == errno) {
3805
4.21M
            GPSD_LOG(LOG_RAW2, &lexer->errout, "PACKET: no bytes ready\n");
3806
4.21M
            recvd = 0;
3807
            // fall through, input buffer may be nonempty
3808
4.21M
        } else {
3809
0
            GPSD_LOG(LOG_WARN, &lexer->errout,
3810
0
                     "PACKET: packet_get1(fd %d) errno: %s(%d)\n",
3811
0
                     fd, strerror(errno), errno);
3812
0
            return -1;
3813
0
        }
3814
4.21M
    } else {
3815
98.6k
        GPSD_LOG(LOG_RAW1, &lexer->errout,
3816
98.6k
                 "PACKET: Read %lld chars to buffer[%zd] (total %lld): %s\n",
3817
98.6k
                 recvd, lexer->inbuflen, lexer->inbuflen + recvd,
3818
98.6k
                 gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
3819
98.6k
                                 lexer->inbufptr, (size_t) recvd));
3820
98.6k
        lexer->inbuflen += recvd;
3821
98.6k
    }
3822
4.31M
    GPSD_LOG(LOG_SPIN, &lexer->errout,
3823
4.31M
             "PACKET: packet_get1(fd %d) recvd %lld %s(%d)\n",
3824
4.31M
             fd, recvd, strerror(errno), errno);
3825
    /*
3826
     * Bail out, indicating no more input, only if we just received
3827
     * nothing from the device and there is nothing waiting in the
3828
     * packet input buffer.
3829
     */
3830
4.31M
    if (0 >= recvd &&
3831
4.27M
        0 >= packet_buffered_input(lexer)) {
3832
3.81M
        GPSD_LOG(LOG_IO, &lexer->errout,
3833
3.81M
                 "PACKET: packet_get1(fd %d) recvd %lld\n",
3834
3.81M
                 fd, recvd);
3835
3.81M
        return recvd;
3836
3.81M
    }
3837
3838
    // Otherwise, consume from the packet input buffer
3839
    // coverity[tainted_data]
3840
492k
    packet_parse(lexer);
3841
3842
    // if input buffer is full, discard
3843
492k
    if (sizeof(lexer->inbuffer) <= (lexer->inbuflen)) {
3844
        // coverity[tainted_data]
3845
0
        packet_discard(lexer);
3846
0
        lexer->state = GROUND_STATE;
3847
0
        GPSD_LOG(LOG_WARN, &lexer->errout,
3848
0
                 "PACKET: packet_get1() inbuffer overflow.\n");
3849
0
    }
3850
3851
    /*
3852
     * If we gathered a packet, return its length; it will have been
3853
     * consumed out of the input buffer and moved to the output
3854
     * buffer.  We don't care whether the read() returned 0 or -1 and
3855
     * gathered packet data was all buffered or whether it was partly
3856
     * just physically read.
3857
     *
3858
     * Note: this choice greatly simplifies life for callers of
3859
     * packet_get1(), but means that they cannot tell when a nonzero
3860
     * return means there was a successful physical read.  They will
3861
     * thus credit a data source that drops out with being alive
3862
     * slightly longer than it actually was.  This is unlikely to
3863
     * matter as long as any policy timeouts are large compared to
3864
     * the time required to consume the greatest possible amount
3865
     * of buffered input, but if you hack this code you need to
3866
     * be aware of the issue. It might also slightly affect
3867
     * performance profiling.
3868
     */
3869
492k
    if (0 < lexer->outbuflen) {
3870
458k
        GPSD_LOG(LOG_IO, &lexer->errout,
3871
458k
                 "PACKET: packet_get1(fd %d) outbuflen %zd\n",
3872
458k
                 fd, lexer->outbuflen);
3873
458k
        return (ssize_t)lexer->outbuflen;
3874
458k
    }
3875
    /*
3876
     * Otherwise recvd is the size of whatever packet fragment we got.
3877
     * It can still be 0 or -1 at this point even if buffer data
3878
     * was consumed.
3879
     */
3880
33.9k
    GPSD_LOG(LOG_IO, &lexer->errout,
3881
33.9k
             "PACKET: packet_get1(fd %d) recvd %lld\n",
3882
33.9k
             fd, recvd);
3883
33.9k
    return recvd;
3884
492k
}
3885
3886
// return the packet machine to the ground state
3887
void packet_reset(struct gps_lexer_t *lexer)
3888
53.5k
{
3889
53.5k
    lexer->type = BAD_PACKET;
3890
53.5k
    lexer->state = GROUND_STATE;
3891
53.5k
    lexer->inbuflen = 0;
3892
53.5k
    lexer->inbufptr = lexer->inbuffer;
3893
53.5k
    isgps_init(lexer);
3894
53.5k
#ifdef STASH_ENABLE
3895
53.5k
    lexer->stashbuflen = 0;
3896
53.5k
#endif  // STASH_ENABLE
3897
53.5k
}
3898
3899
3900
#ifdef __UNUSED__
3901
// push back the last packet grabbed
3902
void packet_pushback(struct gps_lexer_t *lexer)
3903
{
3904
    if (MAX_PACKET_LENGTH > (lexer->outbuflen + lexer->inbuflen)) {
3905
        memmove(lexer->inbuffer + lexer->outbuflen,
3906
                lexer->inbuffer, lexer->inbuflen);
3907
        memmove(lexer->inbuffer, lexer->outbuffer, lexer->outbuflen);
3908
        lexer->inbuflen += lexer->outbuflen;
3909
        lexer->inbufptr += lexer->outbuflen;
3910
        lexer->outbuflen = 0;
3911
    }
3912
}
3913
#endif  // __UNUSED
3914
3915
// vim: set expandtab shiftwidth=4