Coverage Report

Created: 2026-06-04 06:21

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