Coverage Report

Created: 2026-01-09 07:09

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