Coverage Report

Created: 2026-05-30 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_rtcm2.c
Line
Count
Source
1
/*****************************************************************************
2
3
This is a decoder for RTCM-104 2.x, an obscure and complicated serial
4
protocol used for broadcasting pseudorange corrections from
5
differential-GPS reference stations.  The applicable
6
standard is
7
8
RTCM RECOMMENDED STANDARDS FOR DIFFERENTIAL GNSS (GLOBAL NAVIGATION
9
SATELLITE) SERVICE, VERSION 2.3 (RTCM PAPER 136-2001/SC104-STD)
10
11
Ordering instructions are accessible from <http://www.rtcm.org/>
12
under "Publications".  This describes version 2.3 of the RTCM specification.
13
RTCM-104 was later completely redesigned as level 3.0.
14
15
Also applicable is ITU-R M.823: "Technical characteristics of
16
differential transmissions for global navigation satellite systems
17
from maritime radio beacons in the frequency band 283.5 - 315 kHz in
18
region 1 and 285 - 325 kHz in regions 2 & 3."
19
20
The RTCM 2.x protocol uses as a transport layer the GPS satellite downlink
21
protocol described in IS-GPS-200, the Navstar GPS Interface
22
Specification.  This code relies on the lower-level packet-assembly
23
code for that protocol in isgps.c.
24
25
The lower layer's job is done when it has assembled a message of up to
26
33 30-bit words of clean parity-checked data.  At this point this upper layer
27
takes over.  struct rtcm2_msg_t is overlaid on the buffer and the bitfields
28
are used to extract pieces of it.  Those pieces are copied and (where
29
necessary) reassembled into a struct rtcm2_t.
30
31
This code and the contents of isgps.c are evolved from code by
32
Wolfgang Rupprecht.  Wolfgang's decoder was loosely based on one
33
written by John Sager in 1999.  Here are John Sager's original notes:
34
35
The RTCM decoder prints a legible representation of the input data.
36
The RTCM SC-104 specification is copyrighted, so I cannot
37
quote it - in fact, I have never read it! Most of the information
38
used to develop the decoder came from publication ITU-R M.823.
39
This is a specification of the data transmitted from LF DGPS
40
beacons in the 300kHz band. M.823 contains most of those parts of
41
RTCM SC-104 directly relevant to the air interface (there
42
are one or two annoying and vital omissions!). Information
43
about the serial interface format was gleaned from studying
44
the output of a beacon receiver test program made available on
45
Starlink's website.
46
47
This code has been checked against ASCII dumps made by a proprietary
48
decoder running under Windows and is known to be consistent with it
49
with respect to message types 1, 3, 9, 14, 16, and 31.  Decoding of
50
message types 4, 5, 6, 7, and 13 has not been checked. Message types
51
8, 10-12, 15-27, 28-30 (undefined), 31-37, 38-58 (undefined), and
52
60-63 are not yet supported.
53
54
This file is Copyright 2010 by the GPSD project
55
SPDX-License-Identifier: BSD-2-clause
56
57
*****************************************************************************/
58
59
#include "../include/gpsd_config.h"  // must be before all includes
60
61
#include <stdio.h>
62
#include <string.h>
63
64
#include "../include/compiler.h"   // for FALLTHROUGH
65
#include "../include/gpsd.h"
66
67
/*
68
  __BYTE_ORDER__, __ORDER_BIG_ENDIAN__ and __ORDER_LITTLE_ENDIAN__ are
69
  defined in some gcc versions only, probably depending on the
70
  architecture. Try to use endian.h if the gcc way fails - endian.h also
71
  does not seem to be available on all platforms.
72
*/
73
74
#if defined(HAVE_BUILTIN_ENDIANNESS) && HAVE_BUILTIN_ENDIANNESS
75
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
76
#define WORDS_BIGENDIAN 1
77
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
78
#undef WORDS_BIGENDIAN
79
#else
80
#error Unknown endianness!
81
#endif
82
83
#else  // !HAVE_BUILTIN_ENDIANNESS
84
85
#if defined(HAVE_ENDIAN_H)
86
#include <endian.h>
87
#elif defined(HAVE_SYS_ENDIAN_H)
88
#include <sys/endian.h>
89
#elif defined(HAVE_MACHINE_ENDIAN_H)
90
#include <machine/endian.h>
91
#endif
92
93
/*
94
 * Darwin (Mac OS X) uses special defines.
95
 * This must precede the BSD case, since _BIG_ENDIAN may be incorrectly defined
96
 */
97
#if !defined( __BYTE_ORDER) && defined(__DARWIN_BYTE_ORDER)
98
#define __BYTE_ORDER __DARWIN_BYTE_ORDER
99
#endif
100
#if !defined( __BIG_ENDIAN) && defined(__DARWIN_BIG_ENDIAN)
101
#define __BIG_ENDIAN __DARWIN_BIG_ENDIAN
102
#endif
103
#if !defined( __LITTLE_ENDIAN) && defined(__DARWIN_LITTLE_ENDIAN)
104
#define __LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
105
#endif
106
107
/*
108
 * BSD uses _BYTE_ORDER, and Linux uses __BYTE_ORDER.
109
 */
110
#if !defined( __BYTE_ORDER) && defined(_BYTE_ORDER)
111
#define __BYTE_ORDER _BYTE_ORDER
112
#endif
113
#if !defined( __BIG_ENDIAN) && defined(_BIG_ENDIAN)
114
#define __BIG_ENDIAN _BIG_ENDIAN
115
#endif
116
#if !defined( __LITTLE_ENDIAN) && defined(_LITTLE_ENDIAN)
117
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
118
#endif
119
120
#if !defined(__BYTE_ORDER) || !defined(__BIG_ENDIAN) || \
121
    !defined(__LITTLE_ENDIAN)
122
#error endianness macros are not defined
123
#endif
124
125
#if __BYTE_ORDER == __BIG_ENDIAN
126
#define WORDS_BIGENDIAN 1
127
#elif __BYTE_ORDER == __LITTLE_ENDIAN
128
#undef WORDS_BIGENDIAN
129
#else
130
#error Unknown endianness!
131
#endif  //__BYTE_ORDER
132
133
#endif  // !HAVE_BUILTIN_ENDIANNESS
134
135
/*
136
 * Structures for interpreting words in an RTCM-104 2.x message (after
137
 * parity checking and removing inversion).  Note, these structures
138
 * are overlaid on the raw data in order to decode them into
139
 * bitfields; this will fail horribly if your C compiler introduces
140
 * padding between or before bit fields, or between 8-bit-aligned
141
 * bitfields and character arrays despite #pragma pack(1).  The right
142
 * things happen under gcc 4.x on amd64, i386, ia64, all arm and mips
143
 * variants, m68k, and powerpc)
144
 *
145
 * (In practice, the only class of machines on which this is likely
146
 * to fail are word-aligned architectures without barrel shifters.
147
 * Very few of these are left in 2012. By test, we know of s390, s390x,
148
 * and sparc.)
149
 *
150
 * The RTCM 2.1 standard is less explicit than it should be about
151
 * signed-integer representations.  Two's complement is specified for
152
 * some but not all.
153
 */
154
155
5.66k
#define ZCOUNT_SCALE    0.6     // sec
156
586
#define PRCSMALL        0.02    // meters
157
159
#define PRCLARGE        0.32    // meters
158
586
#define RRSMALL         0.002   // meters/sec
159
159
#define RRLARGE         0.032   // meters/sec
160
161
#define MAXPCSMALL     (0x7FFF * PCSMALL)  // 16-bits signed
162
#define MAXRRSMALL     (0x7F   * RRSMALL)  //  8-bits signed
163
164
225
#define XYZ_SCALE       0.01    // meters
165
// extended ECEF scale
166
567
#define EXYZ_SCALE      0.0001  // meters
167
// ECEF delta scale
168
396
#define DXYZ_SCALE      0.1     // meters
169
// extended ECEF delta scale: 1/256 cm
170
874
#define EDXYZ_SCALE     (1.0/256.0)     // centimeter
171
// L2 extended ECEF delta scale: 1/16 cm
172
252
#define EDXYZ2_SCALE     (1.0/16.0)     // centimeter
173
210
#define LA_SCALE        (90.0/32767.0)  // degrees
174
210
#define LO_SCALE        (180.0/32767.0) // degrees
175
210
#define FREQ_SCALE      0.1     // kHz
176
210
#define FREQ_OFFSET     190.0   // kHz
177
72
#define CNR_OFFSET      24      // dB
178
190
#define TU_SCALE        5       // minutes
179
180
374
#define LATLON_SCALE    0.01    // degrees
181
187
#define RANGE_SCALE     4       // kilometers
182
183
#pragma pack(1)
184
185
/*
186
 * Reminder: Emacs reverse-region is useful...
187
 */
188
189
#ifndef WORDS_BIGENDIAN  // little-endian, like x86, amd64
190
191
struct rtcm2_msg_t {
192
    struct rtcm2_msghw1 {                       // header word 1
193
        unsigned int            parity:6;
194
        unsigned int            refstaid:10;    // reference station ID
195
        unsigned int            msgtype:6;      // RTCM message type
196
        unsigned int            preamble:8;     // fixed at 01100110
197
        unsigned int            _pad:2;
198
    } w1;
199
200
    struct rtcm2_msghw2 {                       // header word 2
201
        unsigned int            parity:6;
202
        unsigned int            stathlth:3;     // station health
203
        unsigned int            frmlen:5;
204
        unsigned int            sqnum:3;
205
        unsigned int            zcnt:13;
206
        unsigned int            _pad:2;
207
    } w2;
208
209
    union {
210
        // msg 1 - differential gps corrections
211
        struct rtcm2_msg1 {
212
            struct gps_correction_t {
213
                struct {                        // msg 1 word 3
214
                    unsigned int    parity:6;
215
                    int             prc1:16;
216
                    unsigned int    satident1:5;      // satellite ID
217
                    unsigned int    udre1:2;
218
                    unsigned int    scale1:1;
219
                    unsigned int    _pad:2;
220
                } w3;
221
                struct {                        // msg 1 word 4
222
                    unsigned int    parity:6;
223
                    unsigned int    satident2:5;       // satellite ID
224
                    unsigned int    udre2:2;
225
                    unsigned int    scale2:1;
226
                    unsigned int    iod1:8;
227
                    int             rrc1:8;
228
                    unsigned int    _pad:2;
229
                } w4;
230
                struct {                        // msg 1 word 5
231
                    unsigned int    parity:6;
232
                    int             rrc2:8;
233
                    int             prc2:16;
234
                    unsigned int    _pad:2;
235
                } w5;
236
                struct {                        // msg 1 word
237
                    unsigned int    parity:6;
238
                    int             prc3_h:8;
239
                    unsigned int    satident3:5;        // satellite ID
240
                    unsigned int    udre3:2;
241
                    unsigned int    scale3:1;
242
                    unsigned int    iod2:8;
243
                    unsigned int    _pad:2;
244
                } w6;
245
                struct {                        // msg 1 word 7
246
                    unsigned int    parity:6;
247
                    unsigned int    iod3:8;
248
                    int             rrc3:8;
249
                    // NOTE: unsigned int for low byte
250
                    unsigned int    prc3_l:8;
251
                    unsigned int    _pad:2;
252
                } w7;
253
            } corrections[(RTCM2_WORDS_MAX - 2) / 5];
254
        } type1;
255
256
        /* msg 2 -  Pseudo-range corrections, referring to previous orbit
257
         * data records (maximum 12 satellites) */
258
259
        // msg 3 - reference station parameters
260
        struct rtcm2_msg3 {
261
            struct {
262
                unsigned int        parity:6;
263
                unsigned int        x_h:24;
264
                unsigned int        _pad:2;
265
            } w3;
266
            struct {
267
                unsigned int        parity:6;
268
                unsigned int        y_h:16;
269
                unsigned int        x_l:8;
270
                unsigned int        _pad:2;
271
            } w4;
272
            struct {
273
                unsigned int        parity:6;
274
                unsigned int        z_h:8;
275
                unsigned int        y_l:16;
276
                unsigned int        _pad:2;
277
            } w5;
278
            struct {
279
                unsigned int        parity:6;
280
                unsigned int        z_l:24;
281
                unsigned int        _pad:2;
282
            } w6;
283
        } type3;
284
285
        // msg 4 - reference station datum
286
        struct rtcm2_msg4 {
287
            struct {
288
                unsigned int        parity:6;
289
                unsigned int        datum_alpha_char2:8;
290
                unsigned int        datum_alpha_char1:8;
291
                unsigned int        spare:4;
292
                unsigned int        dat:1;
293
                unsigned int        dgnss:3;
294
                unsigned int        _pad:2;
295
            } w3;
296
            struct {
297
                unsigned int        parity:6;
298
                unsigned int        datum_sub_div_char2:8;
299
                unsigned int        datum_sub_div_char1:8;
300
                unsigned int        datum_sub_div_char3:8;
301
                unsigned int        _pad:2;
302
            } w4;
303
            struct {
304
                unsigned int        parity:6;
305
                unsigned int        dy_h:8;
306
                unsigned int        dx:16;
307
                unsigned int        _pad:2;
308
            } w5;
309
            struct {
310
                unsigned int        parity:6;
311
                unsigned int        dz:24;
312
                unsigned int        dy_l:8;
313
                unsigned int        _pad:2;
314
            } w6;
315
        } type4;
316
317
        // msg 5 - constellation health
318
        struct rtcm2_msg5 {
319
            struct b_health_t {
320
                unsigned int        parity:6;
321
                unsigned int        unassigned:2;
322
                unsigned int        time_unhealthy:4;
323
                unsigned int        loss_warn:1;
324
                unsigned int        new_nav_data:1;
325
                unsigned int        health_enable:1;
326
                unsigned int        cn0:5;
327
                unsigned int        data_health:3;
328
                unsigned int        issue_of_data_link:1;
329
                unsigned int        sat_id:5;
330
                unsigned int        reserved:1;
331
                unsigned int        _pad:2;
332
            } health[MAXHEALTH];
333
        } type5;
334
335
        // msg 6 - null message
336
337
        // msg 7 - beacon almanac
338
        struct rtcm2_msg7 {
339
            struct b_station_t {
340
                struct {
341
                    unsigned int    parity:6;
342
                    int             lon_h:8;
343
                    int             lat:16;
344
                    unsigned int    _pad:2;
345
                } w3;
346
                struct {
347
                    unsigned int    parity:6;
348
                    unsigned int    freq_h:6;
349
                    unsigned int    range:10;
350
                    unsigned int    lon_l:8;
351
                    unsigned int    _pad:2;
352
                } w4;
353
                struct {
354
                    unsigned int    parity:6;
355
                    unsigned int    encoding:1;
356
                    unsigned int    sync_type:1;
357
                    unsigned int    mod_mode:1;
358
                    unsigned int    bit_rate:3;
359
                    /*
360
                     * ITU-R M.823-2 page 9 and RTCM-SC104 v2.1 pages
361
                     * 4-21 and 4-22 are in conflict over the next two
362
                     * field sizes.  ITU says 9+3, RTCM says 10+2.
363
                     * The latter correctly decodes the USCG station
364
                     * id's so I'll use that one here. -wsr
365
                     */
366
                    unsigned int    station_id:10;
367
                    unsigned int    health:2;
368
                    unsigned int    freq_l:6;
369
                    unsigned int    _pad:2;
370
                } w5;
371
            } almanac[32];
372
        } type7;
373
374
        // msg 8 - Pseudolite almanac
375
376
        // msg 9 - GPS Partial correction set
377
378
        // msg 10 - P-code differential corrections
379
380
        // msg 11 - C/A-code L1, L2 delta corrections
381
382
        // msg 12 - Pseudolite station parameters.
383
384
        // msg 13 - Ground Transmitter Parameters (RTCM2.3 only)
385
        struct rtcm2_msg13 {
386
            struct {
387
                unsigned int        parity:6;
388
                int                 lat:16;
389
                unsigned int        reserved:6;
390
                unsigned int        rangeflag:1;
391
                unsigned int        status:1;
392
                unsigned int        _pad:2;
393
            } w1;
394
            struct {
395
                unsigned int        parity:6;
396
                unsigned int        range:8;
397
                int                 lon:16;
398
                unsigned int        _pad:2;
399
            } w2;
400
        } type13;
401
402
        // msg 14 - GPS Time of Week (RTCM2.3 only)
403
        struct rtcm2_msg14 {
404
            struct {
405
                unsigned int        parity:6;
406
                unsigned int        leapsecs:6;
407
                unsigned int        hour:8;
408
                unsigned int        week:10;
409
                unsigned int        _pad:2;
410
            } w1;
411
        } type14;
412
413
        // msg 15 - Ionospheric delay message
414
415
        // msg 16 - text msg
416
        struct rtcm2_msg16 {
417
            struct {
418
                unsigned int        parity:6;
419
                unsigned int        byte3:8;
420
                unsigned int        byte2:8;
421
                unsigned int        byte1:8;
422
                unsigned int        _pad:2;
423
            } txt[RTCM2_WORDS_MAX-2];
424
        } type16;
425
426
        // msg 17 - GPS ephmerides.  RTCM 2.1
427
428
        // msg 18 - RTK uncorrected carrier phases.  RTCM 2.1
429
        struct rtcm2_msg18 {
430
            unsigned int        parity:6;
431
            unsigned int        tom:20;
432
            unsigned int        r:2;
433
            unsigned int        f:2;
434
            unsigned int        _pad:2;
435
            struct {
436
                unsigned int        parity:6;
437
                unsigned int        cp_h:8;
438
                unsigned int        clc:5;
439
                unsigned int        dq:3;
440
                unsigned int        ident:5;
441
                unsigned int        g:1;
442
                unsigned int        pc:1;
443
                unsigned int        m:1;
444
                unsigned int        _pad:2;
445
                unsigned int        parity1:6;
446
                unsigned int        cp_l:24;
447
                unsigned int        _pad1:2;
448
            } sat[15];
449
        } type18;
450
451
        // msg 19 - RTK uncorrected pseudoranges.  RTCM 2.1
452
        struct rtcm2_msg19 {
453
            unsigned int        parity:6;
454
            unsigned int        tom:20;
455
            unsigned int        sm:2;
456
            unsigned int        f:2;
457
            unsigned int        _pad:2;
458
            struct {
459
                unsigned int        parity:6;
460
                unsigned int        pr_h:8;
461
                unsigned int        me:4;
462
                unsigned int        dq:4;
463
                unsigned int        ident:5;
464
                unsigned int        g:1;
465
                unsigned int        pc:1;
466
                unsigned int        m:1;
467
                unsigned int        _pad:2;
468
                unsigned int        parity1:6;
469
470
                unsigned int        pr_l:24;
471
                unsigned int        _pad1:2;
472
            } sat[15];
473
        } type19;
474
475
        // msg 20 - RTK carrier phase corrections.  RTCM 2.1
476
        struct rtcm2_msg20 {
477
            unsigned int        parity:6;
478
            unsigned int        tom:20;
479
            unsigned int        r:2;
480
            unsigned int        f:2;
481
            unsigned int        _pad:2;
482
            struct {
483
                unsigned int        parity:6;
484
                unsigned int        iod:8;
485
                unsigned int        clc:5;
486
                unsigned int        dq:3;
487
                unsigned int        ident:5;
488
                unsigned int        g:1;
489
                unsigned int        pc:1;
490
                unsigned int        m:1;
491
                unsigned int        _pad:2;
492
                unsigned int        parity1:6;
493
                unsigned int        cpc:24;
494
                unsigned int        _pad1:2;
495
            } sat[RTCM2_WORDS_MAX / 2];
496
        } type20;
497
498
        // msg 21 - RTK/high accuracy pseudorange corrections.  RTCM 2.1
499
        struct rtcm2_msg21 {
500
            unsigned int        parity:6;
501
            unsigned int        tom:20;
502
            unsigned int        sm:2;
503
            unsigned int        f:2;
504
            unsigned int        _pad:2;
505
        } type21;
506
507
        // msg 22 - Extended reference station parameters
508
        struct rtcm2_msg22 {
509
            unsigned int        parity:6;
510
            int                 ecef_dz:8;
511
            int                 ecef_dy:8;
512
            int                 ecef_dx:8;
513
            unsigned int        _pad:2;
514
            // word 4
515
            unsigned int        parity1:6;
516
            unsigned int        ah:18;
517
            unsigned int        nh:1;
518
            unsigned int        ap:1;
519
            unsigned int        at:1;
520
            unsigned int        gs:1;
521
            unsigned int        res:2;
522
            unsigned int        _pad1:2;
523
            // word 5
524
            unsigned int        parity2:6;
525
            int                 ecef_dz2:8;
526
            int                 ecef_dy2:8;
527
            int                 ecef_dx2:8;
528
            unsigned int        _pad2:2;
529
        } type22;
530
531
        // msg 23 - Type of Antenna.  RTCM 2.3
532
        struct rtcm2_msg23 {
533
            struct {
534
                unsigned int        parity:6;
535
                unsigned char       byte2:8;
536
                unsigned char       byte1:8;
537
                unsigned char       byte0:8;
538
                unsigned int        _pad:2;
539
            } words[RTCM2_WORDS_MAX - 2];
540
        } type23;
541
542
        // msg 24 - Reference station ARP..  RTCM 2.3
543
        struct rtcm2_msg24 {
544
            struct {
545
                unsigned int        parity:6;
546
                unsigned int        x_h:24;
547
                unsigned int        _pad:2;
548
            } w3;
549
            struct {
550
                unsigned int        parity:6;
551
                unsigned int        y_h:8;
552
                unsigned int        r:2;
553
                unsigned int        x_l:14;
554
                unsigned int        _pad:2;
555
            } w4;
556
            struct {
557
                unsigned int        parity:6;
558
                unsigned int        y_m:24;
559
                unsigned int        _pad:2;
560
            } w5;
561
            struct {
562
                unsigned int        parity:6;
563
                unsigned int        z_h:16;
564
                unsigned int        r:2;
565
                unsigned int        y_l:6;
566
                unsigned int        _pad:2;
567
            } w6;
568
            struct {
569
                unsigned int        parity:6;
570
                unsigned int        ah:1;
571
                unsigned int        gs:1;
572
                unsigned int        z_l:22;
573
                unsigned int        _pad:2;
574
            } w7;
575
            struct {
576
                unsigned int        parity:6;
577
                unsigned int        res:6;
578
                unsigned int        ah:18;
579
                unsigned int        _pad:2;
580
            } w8;
581
        } type24;
582
583
        // msg 27 -  Extended almanac of DGPS.
584
585
        // msg 31 - differential GLONASS corrections
586
        struct rtcm2_msg31 {
587
            struct glonass_correction_t {
588
                struct {                        // msg 1 word 3
589
                    unsigned int    parity:6;
590
                    int             prc1:16;
591
                    unsigned int    satident1:5;        // satellite ID
592
                    unsigned int    udre1:2;
593
                    unsigned int    scale1:1;
594
                    unsigned int    _pad:2;
595
                } w3;
596
597
                struct {                        // msg 1 word 4
598
                    unsigned int    parity:6;
599
                    unsigned int    satident2:5;        // satellite ID
600
                    unsigned int    udre2:2;
601
                    unsigned int    scale2:1;
602
                    unsigned int    tod1:7;
603
                    unsigned int    change1:1;
604
                    int             rrc1:8;
605
                    unsigned int    _pad:2;
606
                } w4;
607
608
                struct {                        // msg 1 word 5
609
                    unsigned int    parity:6;
610
                    int             rrc2:8;
611
                    int             prc2:16;
612
                    unsigned int    _pad:2;
613
                } w5;
614
615
                struct {                        // msg 1 word 6
616
                    unsigned int    parity:6;
617
                    int             prc3_h:8;
618
                    unsigned int    satident3:5;        // satellite ID
619
                    unsigned int    udre3:2;
620
                    unsigned int    scale3:1;
621
                    unsigned int    tod2:7;
622
                    unsigned int    change2:1;
623
                    unsigned int    _pad:2;
624
                } w6;
625
626
                struct {                        // msg 1 word 7
627
                    unsigned int    parity:6;
628
                    unsigned int    tod3:7;
629
                    unsigned int    change3:1;
630
                    int             rrc3:8;
631
                    // NOTE: unsigned int for low byte
632
                    unsigned int    prc3_l:8;
633
                    unsigned int    _pad:2;
634
                } w7;
635
            } corrections[(RTCM2_WORDS_MAX - 2) / 5];
636
        } type31;
637
638
        // msg 32 - Differential GLONASS reference station parameters, RTCM 2.3
639
640
        // msg 33 - GLONASS constellation health, RTCM 2.3
641
642
        // msg 34 - DGLONASS corrections, RTCM 2.3
643
644
        // msg 35 - GLONASS radiobeacon almanac, RTCM 2.3
645
646
        // msg 36 - GLONASS special message, RTCM 2.3
647
648
        // msg 37 - GNSS system time offset, RTCM 2.3
649
650
        /* msg 59 -  Proprietary messages, for transmission of any
651
         * required data */
652
653
        // msg 60-63 - Multipurpose usage
654
655
        // unknown message
656
        isgps30bits_t   rtcm2_msgunk[RTCM2_WORDS_MAX - 2];
657
    } msg_type;
658
} __attribute__((__packed__));
659
660
#endif  // LITTLE_ENDIAN
661
662
#ifdef WORDS_BIGENDIAN
663
664
struct rtcm2_msg_t {
665
    struct rtcm2_msghw1 {                       // header word 1
666
        unsigned int            _pad:2;
667
        unsigned int            preamble:8;     // fixed at 01100110
668
        unsigned int            msgtype:6;      // RTCM message type
669
        unsigned int            refstaid:10;    // reference station ID
670
        unsigned int            parity:6;
671
    } w1;
672
673
    struct rtcm2_msghw2 {                       // header word 2
674
        unsigned int            _pad:2;
675
        unsigned int            zcnt:13;
676
        unsigned int            sqnum:3;
677
        unsigned int            frmlen:5;
678
        unsigned int            stathlth:3;     // station health
679
        unsigned int            parity:6;
680
    } w2;
681
682
    union {
683
        // msg 1 - differential GPS corrections
684
        struct rtcm2_msg1 {
685
            struct gps_correction_t {
686
                struct {                        // msg 1 word 3
687
                    unsigned int    _pad:2;
688
                    unsigned int    scale1:1;
689
                    unsigned int    udre1:2;
690
                    unsigned int    satident1:5;  // satellite ID
691
                    int             prc1:16;
692
                    unsigned int    parity:6;
693
                } w3;
694
695
                struct {                        // msg 1 word 4
696
                    unsigned int    _pad:2;
697
                    int             rrc1:8;
698
                    unsigned int    iod1:8;
699
                    unsigned int    scale2:1;
700
                    unsigned int    udre2:2;
701
                    unsigned int    satident2:5;        // satellite ID
702
                    unsigned int    parity:6;
703
                } w4;
704
705
                struct {                        // msg 1 word 5
706
                    unsigned int    _pad:2;
707
                    int             prc2:16;
708
                    int             rrc2:8;
709
                    unsigned int    parity:6;
710
                } w5;
711
712
                struct {                        // msg 1 word 6
713
                    unsigned int    _pad:2;
714
                    unsigned int    iod2:8;
715
                    unsigned int    scale3:1;
716
                    unsigned int    udre3:2;
717
                    unsigned int    satident3:5;        // satellite ID
718
                    int             prc3_h:8;
719
                    unsigned int    parity:6;
720
                } w6;
721
722
                struct {                        // msg 1 word 7
723
                    unsigned int    _pad:2;
724
                    unsigned int    prc3_l:8;   // NOTE: unsigned for low byte
725
                    int             rrc3:8;
726
                    unsigned int    iod3:8;
727
                    unsigned int    parity:6;
728
                } w7;
729
            } corrections[(RTCM2_WORDS_MAX - 2) / 5];
730
        } type1;
731
732
        /* msg 2 -  Pseudo-range corrections, referring to previous orbit
733
         * data records (maximum 12 satellites) */
734
735
        // msg 3 - reference station parameters
736
        struct rtcm2_msg3 {
737
            struct {
738
                unsigned int        _pad:2;
739
                unsigned int        x_h:24;
740
                unsigned int        parity:6;
741
            } w3;
742
            struct {
743
                unsigned int        _pad:2;
744
                unsigned int        x_l:8;
745
                unsigned int        y_h:16;
746
                unsigned int        parity:6;
747
            } w4;
748
            struct {
749
                unsigned int        _pad:2;
750
                unsigned int        y_l:16;
751
                unsigned int        z_h:8;
752
                unsigned int        parity:6;
753
            } w5;
754
            struct {
755
                unsigned int        _pad:2;
756
                unsigned int        z_l:24;
757
                unsigned int        parity:6;
758
            } w6;
759
        } type3;
760
761
        // msg 4 - reference station datum
762
        struct rtcm2_msg4 {
763
            struct {
764
                unsigned int        _pad:2;
765
                unsigned int        dgnss:3;
766
                unsigned int        dat:1;
767
                unsigned int        spare:4;
768
                unsigned int        datum_alpha_char1:8;
769
                unsigned int        datum_alpha_char2:8;
770
                unsigned int        parity:6;
771
            } w3;
772
            struct {
773
                unsigned int        _pad:2;
774
                unsigned int        datum_sub_div_char3:8;
775
                unsigned int        datum_sub_div_char1:8;
776
                unsigned int        datum_sub_div_char2:8;
777
                unsigned int        parity:6;
778
            } w4;
779
            struct {
780
                unsigned int        _pad:2;
781
                unsigned int        dx:16;
782
                unsigned int        dy_h:8;
783
                unsigned int        parity:6;
784
            } w5;
785
            struct {
786
                unsigned int        _pad:2;
787
                unsigned int        dy_l:8;
788
                unsigned int        dz:24;
789
                unsigned int        parity:6;
790
            } w6;
791
        } type4;
792
793
        // msg 5 - constellation health
794
        struct rtcm2_msg5 {
795
            struct b_health_t {
796
                unsigned int        _pad:2;
797
                unsigned int        reserved:1;
798
                unsigned int        sat_id:5;
799
                unsigned int        issue_of_data_link:1;
800
                unsigned int        data_health:3;
801
                unsigned int        cn0:5;
802
                unsigned int        health_enable:1;
803
                unsigned int        new_nav_data:1;
804
                unsigned int        loss_warn:1;
805
                unsigned int        time_unhealthy:4;
806
                unsigned int        unassigned:2;
807
                unsigned int        parity:6;
808
            } health[MAXHEALTH];
809
        } type5;
810
811
        // msg - 6 -  Null message, used as filler record during time-outs
812
813
        // msg 7 - beacon almanac
814
        struct rtcm2_msg7 {
815
            struct b_station_t {
816
                struct {
817
                    unsigned int    _pad:2;
818
                    int             lat:16;
819
                    int             lon_h:8;
820
                    unsigned int    parity:6;
821
                } w3;
822
                struct {
823
                    unsigned int    _pad:2;
824
                    unsigned int    lon_l:8;
825
                    unsigned int    range:10;
826
                    unsigned int    freq_h:6;
827
                    unsigned int    parity:6;
828
                } w4;
829
                struct {
830
                    unsigned int    _pad:2;
831
                    unsigned int    freq_l:6;
832
                    unsigned int    health:2;
833
                    unsigned int    station_id:10;
834
                             // see comments in LE struct above.
835
                    unsigned int    bit_rate:3;
836
                    unsigned int    mod_mode:1;
837
                    unsigned int    sync_type:1;
838
                    unsigned int    encoding:1;
839
                    unsigned int    parity:6;
840
                } w5;
841
            } almanac[32];
842
        } type7;
843
844
        // msg 8 - Pseudolite almanac
845
846
        // msg 9 - GPS Partial correction set
847
848
        // msg 10 - P-code differential corrections
849
850
        // msg 11 - C/A-code L1, L2 delta corrections
851
852
        // msg 12 - Pseudolite station parameters.
853
854
        // msg 13 - Ground Transmitter Parameters (RTCM2.3 only)
855
        struct rtcm2_msg13 {
856
            struct {
857
                unsigned int        _pad:2;
858
                unsigned int        status:1;
859
                unsigned int        rangeflag:1;
860
                unsigned int        reserved:6;
861
                int                 lat:16;
862
                unsigned int        parity:6;
863
            } w1;
864
            struct {
865
                unsigned int        _pad:2;
866
                int                 lon:16;
867
                unsigned int        range:8;
868
                unsigned int        parity:6;
869
            } w2;
870
        } type13;
871
872
        // msg 14 - GPS Time of Week (RTCM2.3 only)
873
        struct rtcm2_msg14 {
874
            struct {
875
                unsigned int        _pad:2;
876
                unsigned int        week:10;
877
                unsigned int        hour:8;
878
                unsigned int        leapsecs:6;
879
                unsigned int        parity:6;
880
            } w1;
881
        } type14;
882
883
        // msg 15 - Ionospheric delay message
884
885
        // msg 16 - text msg
886
        struct rtcm2_msg16 {
887
            struct {
888
                unsigned int        _pad:2;
889
                unsigned int        byte1:8;
890
                unsigned int        byte2:8;
891
                unsigned int        byte3:8;
892
                unsigned int        parity:6;
893
            } txt[RTCM2_WORDS_MAX-2];
894
        } type16;
895
896
        // msg 17 - GPS ephmerides.  RTCM 2.1
897
898
        // msg 18 - RTK uncorrected carrier phases.  RTCM 2.1
899
        struct rtcm2_msg18 {
900
            unsigned int        _pad:2;
901
            unsigned int        f:2;
902
            unsigned int        r:2;
903
            unsigned int        tom:20;
904
            unsigned int        parity:6;
905
            struct {
906
                unsigned int        _pad:2;
907
                unsigned int        m:1;
908
                unsigned int        pc:1;
909
                unsigned int        g:1;
910
                unsigned int        ident:5;
911
                unsigned int        dq:3;
912
                unsigned int        clc:5;
913
                unsigned int        cp_h:8;
914
                unsigned int        parity:6;
915
                unsigned int        _pad1:2;
916
                unsigned int        cp_l:24;
917
                unsigned int        parity1:6;
918
            } sat[15];
919
        } type18;
920
921
        // msg 19 - RTK uncorrected pseudoranges.  RTCM 2.1
922
        struct rtcm2_msg19 {
923
            unsigned int        _pad:2;
924
            unsigned int        f:2;
925
            unsigned int        sm:2;
926
            unsigned int        tom:20;
927
            unsigned int        parity:6;
928
            struct {
929
                unsigned int        _pad:2;
930
                unsigned int        m:1;
931
                unsigned int        pc:1;
932
                unsigned int        g:1;
933
                unsigned int        ident:5;
934
                unsigned int        dq:4;
935
                unsigned int        me:4;
936
                unsigned int        pr_h:8;
937
                unsigned int        parity:6;
938
939
                unsigned int        _pad1:2;
940
                unsigned int        pr_l:24;
941
                unsigned int        parity1:6;
942
            } sat[15];
943
        } type19;
944
945
        // msg 20 - RTK carrier phase corrections.  RTCM 2.1
946
        struct rtcm2_msg20 {
947
            unsigned int        _pad:2;
948
            unsigned int        f:2;
949
            unsigned int        r:2;
950
            unsigned int        tom:20;
951
            unsigned int        parity:6;
952
            struct {
953
                unsigned int        _pad:2;
954
                unsigned int        m:1;
955
                unsigned int        pc:1;
956
                unsigned int        g:1;
957
                unsigned int        dq:3;
958
                unsigned int        ident:5;
959
                unsigned int        clc:5;
960
                unsigned int        iod:8;
961
                unsigned int        parity:6;
962
                unsigned int        _pad1:2;
963
                unsigned int        cpc:24;
964
                unsigned int        parity1:6;
965
            } sat[RTCM2_WORDS_MAX / 2];
966
        } type20;
967
968
        // msg 21 - RTK/high accuracy pseudorange corrections.  RTCM 2.1
969
        struct rtcm2_msg21 {
970
            unsigned int        _pad:2;
971
            unsigned int        f:2;
972
            unsigned int        sm:2;
973
            unsigned int        tom:20;
974
            unsigned int        parity:6;
975
        } type21;
976
977
        // msg 22 - Extended reference station parameters
978
        struct rtcm2_msg22 {
979
            unsigned int        _pad:2;
980
            int                 ecef_dx:8;
981
            int                 ecef_dy:8;
982
            int                 ecef_dz:8;
983
            unsigned int        parity:6;
984
            // word 4
985
            unsigned int        _pad1:2;
986
            unsigned int        res:2;
987
            unsigned int        gs:1;
988
            unsigned int        at:1;
989
            unsigned int        ap:1;
990
            unsigned int        nh:1;
991
            unsigned int        ah:18;
992
            unsigned int        parity1:6;
993
            // word 5
994
            unsigned int        _pad2:2;
995
            int                 ecef_dx2:8;
996
            int                 ecef_dy2:8;
997
            int                 ecef_dz2:8;
998
            unsigned int        parity2:6;
999
        } type22;
1000
1001
        // msg 23 - Type of Antenna.  RTCM 2.3
1002
        struct rtcm2_msg23 {
1003
            struct {
1004
                unsigned int        _pad:2;
1005
                unsigned char       byte0:8;
1006
                unsigned char       byte1:8;
1007
                unsigned char       byte2:8;
1008
                unsigned int        parity:6;
1009
            } words[RTCM2_WORDS_MAX - 2];
1010
        } type23;
1011
1012
        // msg 24 - Reference station ARP..  RTCM 2.3
1013
        struct rtcm2_msg24 {
1014
            struct {
1015
                unsigned int        _pad:2;
1016
                unsigned int        x_h:24;
1017
                unsigned int        parity:6;
1018
            } w3;
1019
            struct {
1020
                unsigned int        _pad:2;
1021
                unsigned int        x_l:14;
1022
                unsigned int        r:2;
1023
                unsigned int        y_h:8;
1024
                unsigned int        parity:6;
1025
            } w4;
1026
            struct {
1027
                unsigned int        _pad:2;
1028
                unsigned int        y_m:24;
1029
                unsigned int        parity:6;
1030
            } w5;
1031
            struct {
1032
                unsigned int        _pad:2;
1033
                unsigned int        y_l:6;
1034
                unsigned int        r:2;
1035
                unsigned int        z_h:16;
1036
                unsigned int        parity:6;
1037
            } w6;
1038
            struct {
1039
                unsigned int        _pad:2;
1040
                unsigned int        z_l:22;
1041
                unsigned int        gs:1;
1042
                unsigned int        ah:1;
1043
                unsigned int        parity:6;
1044
            } w7;
1045
            struct {
1046
                unsigned int        _pad:2;
1047
                unsigned int        ah:18;
1048
                unsigned int        res:6;
1049
                unsigned int        parity:6;
1050
            } w8;
1051
        } type24;
1052
1053
        // msg 27 -  Extended almanac of DGPS.
1054
1055
        // msg 31 - differential GLONASS corrections
1056
        struct rtcm2_msg31 {
1057
            struct glonass_correction_t {
1058
                struct {                        // msg 1 word 3
1059
                    unsigned int    _pad:2;
1060
                    unsigned int    scale1:1;
1061
                    unsigned int    udre1:2;
1062
                    unsigned int    satident1:5;        // satellite ID
1063
                    int             prc1:16;
1064
                    unsigned int    parity:6;
1065
                } w3;
1066
1067
                struct {                        // msg 1 word 4
1068
                    unsigned int    _pad:2;
1069
                    int             rrc1:8;
1070
                    unsigned int    change1:1;
1071
                    unsigned int    tod1:7;
1072
                    unsigned int    scale2:1;
1073
                    unsigned int    udre2:2;
1074
                    unsigned int    satident2:5;        // satellite ID
1075
                    unsigned int    parity:6;
1076
                } w4;
1077
1078
                struct {                        // msg 1 word 5
1079
                    unsigned int    _pad:2;
1080
                    int             prc2:16;
1081
                    int             rrc2:8;
1082
                    unsigned int    parity:6;
1083
                } w5;
1084
1085
                struct {                        // msg 1 word 6
1086
                    unsigned int    _pad:2;
1087
                    unsigned int    change2:1;
1088
                    unsigned int    tod2:7;
1089
                    unsigned int    scale3:1;
1090
                    unsigned int    udre3:2;
1091
                    unsigned int    satident3:5;        // satellite ID
1092
                    int             prc3_h:8;
1093
                    unsigned int    parity:6;
1094
                } w6;
1095
1096
                struct {                        // msg 1 word 7
1097
                    unsigned int    _pad:2;
1098
                    unsigned int    prc3_l:8;   // NOTE: unsigned for low byte
1099
                    int             rrc3:8;
1100
                    unsigned int    change3:1;
1101
                    unsigned int    tod3:7;
1102
                    unsigned int    parity:6;
1103
                } w7;
1104
            } corrections[(RTCM2_WORDS_MAX - 2) / 5];
1105
        } type31;
1106
1107
        // msg 32 - Differential GLONASS reference station parameters, RTCM 2.3
1108
1109
        // msg 33 - GLONASS constellation health, RTCM 2.3
1110
1111
        // msg 34 - DGLONASS corrections, RTCM 2.3
1112
1113
        // msg 35 - GLONASS radiobeacon almanac, RTCM 2.3
1114
1115
        // msg 36 - GLONASS special message, RTCM 2.3
1116
1117
        // msg 37 - GNSS system time offset, RTCM 2.3
1118
1119
        /* msg 59 -  Proprietary messages, for transmission of any
1120
         * required data */
1121
1122
        // msg 60-63 - Multipurpsoe usage
1123
1124
        // unknown message
1125
        isgps30bits_t   rtcm2_msgunk[RTCM2_WORDS_MAX-2];
1126
    } msg_type;
1127
} __attribute__((__packed__));
1128
1129
#endif  // BIG ENDIAN
1130
1131
621M
#define PREAMBLE_PATTERN 0x66
1132
1133
static unsigned int tx_speed[] = { 25, 50, 100, 110, 150, 200, 250, 300 };
1134
1135
#define DIMENSION(a) (unsigned)(sizeof(a)/sizeof(a[0]))
1136
1137
// break out the raw bits into the content fields
1138
void rtcm2_unpack(struct gps_device_t *session, struct rtcm2_t *tp, char *buf)
1139
5.66k
{
1140
5.66k
    unsigned len;
1141
5.66k
    unsigned n, w;
1142
5.66k
    struct rtcm2_msg_t *msg = (struct rtcm2_msg_t *)buf;
1143
5.66k
    bool unknown = true;              // we don't know how to decode
1144
5.66k
    const char *msg_name = NULL;      // no decode, but maybe we know the name
1145
1146
5.66k
    tp->type = msg->w1.msgtype;         // 1 to 64.  Zero means 64
1147
5.66k
    tp->refstaid = msg->w1.refstaid;    // 0 to 1023
1148
5.66k
    tp->length = msg->w2.frmlen;        // 0 to 31
1149
5.66k
    tp->zcount = msg->w2.zcnt * ZCOUNT_SCALE;  // 0 to 3599.4 sec
1150
5.66k
    tp->seqnum = msg->w2.sqnum;         // 0 to 7
1151
5.66k
    tp->stathlth = msg->w2.stathlth;
1152
1153
5.66k
    if (31 < tp->length) {
1154
0
        GPSD_LOG(LOG_ERROR, &session->context->errout,
1155
0
                 "RTCM2: tp->tplength too long %dd\n",
1156
0
                 tp->length);
1157
0
        return;
1158
0
    }
1159
    // clear rtk struct
1160
5.66k
    memset(&tp->rtk, 0, sizeof(tp->rtk));
1161
1162
    // clear ref_sta struct
1163
5.66k
    memset(&tp->ref_sta, 0, sizeof(tp->ref_sta));
1164
5.66k
    tp->ref_sta.x = NAN;
1165
5.66k
    tp->ref_sta.y = NAN;
1166
5.66k
    tp->ref_sta.z = NAN;
1167
5.66k
    tp->ref_sta.dx = NAN;
1168
5.66k
    tp->ref_sta.dy = NAN;
1169
5.66k
    tp->ref_sta.dz = NAN;
1170
5.66k
    tp->ref_sta.ah = NAN;
1171
5.66k
    tp->ref_sta.dx2 = NAN;
1172
5.66k
    tp->ref_sta.dy2 = NAN;
1173
5.66k
    tp->ref_sta.dz2 = NAN;
1174
1175
    // FIXME: test tp->length + 2, against session->lexer.isgps.buflen,
1176
1177
    // len does not include 2 byte header
1178
5.66k
    len = tp->length;
1179
5.66k
    n = 0;
1180
5.66k
    switch (tp->type) {
1181
235
    case 1:
1182
235
        FALLTHROUGH
1183
345
    case 9:
1184
345
    {
1185
345
        int lens = (int)len;
1186
345
        struct gps_correction_t *m = &msg->msg_type.type1.corrections[0];
1187
345
        msg_name = "Differential GPS Corrections";
1188
345
        unknown = false;
1189
1190
785
        while (0 <= lens) {
1191
440
            if (2 <= lens) {
1192
195
                tp->gps_ranges.sat[n].ident = m->w3.satident1;
1193
195
                tp->gps_ranges.sat[n].udre = m->w3.udre1;
1194
195
                tp->gps_ranges.sat[n].iod = m->w4.iod1;
1195
195
                tp->gps_ranges.sat[n].prc = m->w3.prc1 *
1196
195
                    (m->w3.scale1 ? PRCLARGE : PRCSMALL);
1197
195
                tp->gps_ranges.sat[n].rrc = m->w4.rrc1 *
1198
195
                    (m->w3.scale1 ? RRLARGE : RRSMALL);
1199
195
                n++;
1200
195
            }
1201
440
            if (4 <= lens) {
1202
127
                tp->gps_ranges.sat[n].ident = m->w4.satident2;
1203
127
                tp->gps_ranges.sat[n].udre = m->w4.udre2;
1204
127
                tp->gps_ranges.sat[n].iod = m->w6.iod2;
1205
127
                tp->gps_ranges.sat[n].prc = m->w5.prc2 *
1206
127
                    (m->w4.scale2 ? PRCLARGE : PRCSMALL);
1207
127
                tp->gps_ranges.sat[n].rrc = m->w5.rrc2 *
1208
127
                    (m->w4.scale2 ? RRLARGE : RRSMALL);
1209
127
                n++;
1210
127
            }
1211
440
            if (5 <= lens) {
1212
95
                tp->gps_ranges.sat[n].ident = m->w6.satident3;
1213
95
                tp->gps_ranges.sat[n].udre = m->w6.udre3;
1214
95
                tp->gps_ranges.sat[n].iod = m->w7.iod3;
1215
95
                tp->gps_ranges.sat[n].prc =
1216
95
                    ((m->w6.prc3_h << 8) | (m->w7.prc3_l)) *
1217
95
                    (m->w6.scale3 ? PRCLARGE : PRCSMALL);
1218
95
                tp->gps_ranges.sat[n].rrc =
1219
95
                    m->w7.rrc3 * (m->w6.scale3 ? RRLARGE : RRSMALL);
1220
95
                n++;
1221
95
            }
1222
440
            lens -= 5;
1223
440
            m++;
1224
440
        }
1225
345
        tp->gps_ranges.nentries = n;
1226
345
    }
1227
345
        break;
1228
1229
82
    case 2:
1230
82
        msg_name = "Delta Differential GPS Corrections";
1231
82
        break;
1232
1233
163
    case 3:
1234
163
        {
1235
163
            struct rtcm2_msg3 *m = &msg->msg_type.type3;
1236
163
            msg_name = "Reference Station Parameters (GPS)";
1237
163
            unknown = false;
1238
1239
163
            if (4 <= len) {
1240
75
                tp->ref_sta.valid = true;
1241
75
                tp->ref_sta.x = ((m->w3.x_h << 8) | (m->w4.x_l)) * XYZ_SCALE;
1242
75
                tp->ref_sta.y = ((m->w4.y_h << 16) | (m->w5.y_l)) * XYZ_SCALE;
1243
75
                tp->ref_sta.z = ((m->w5.z_h << 24) | (m->w6.z_l)) * XYZ_SCALE;
1244
75
            }
1245
163
        }
1246
163
        break;
1247
1248
370
    case 4:
1249
370
        msg_name = "Reference Station Datum";
1250
370
        unknown = false;
1251
370
        if (2 <= len) {
1252
288
            struct rtcm2_msg4 *m = &msg->msg_type.type4;
1253
288
            tp->reference.valid = true;
1254
1255
288
            tp->reference.system =
1256
288
                (m->w3.dgnss == 0) ? NAVSYSTEM_GPS :
1257
288
                ((m->w3.dgnss == 1) ? NAVSYSTEM_GLONASS : NAVSYSTEM_UNKNOWN);
1258
288
            tp->reference.sense =
1259
288
                (m->w3.dat != 0) ? SENSE_GLOBAL : SENSE_LOCAL;
1260
288
            if (m->w3.datum_alpha_char1) {
1261
124
                tp->reference.datum[n++] = (char)(m->w3.datum_alpha_char1);
1262
124
            }
1263
288
            if (m->w3.datum_alpha_char2) {
1264
65
                tp->reference.datum[n++] = (char)(m->w3.datum_alpha_char2);
1265
65
            }
1266
288
            if (m->w4.datum_sub_div_char1) {
1267
129
                tp->reference.datum[n++] = (char)(m->w4.datum_sub_div_char1);
1268
129
            }
1269
288
            if (m->w4.datum_sub_div_char2) {
1270
129
                tp->reference.datum[n++] = (char)(m->w4.datum_sub_div_char2);
1271
129
            }
1272
288
            if (m->w4.datum_sub_div_char3) {
1273
129
                tp->reference.datum[n++] = (char)(m->w4.datum_sub_div_char3);
1274
129
            }
1275
            // we used to say n++ here, but scan-build complains
1276
288
            tp->reference.datum[n] = '\0';
1277
288
            if (4 <= len) {
1278
132
                tp->reference.dx = m->w5.dx * DXYZ_SCALE;
1279
132
                tp->reference.dy =
1280
132
                    ((m->w5.dy_h << 8) | m->w6.dy_l) * DXYZ_SCALE;
1281
132
                tp->reference.dz = m->w6.dz * DXYZ_SCALE;
1282
132
            } else
1283
156
                tp->reference.sense = SENSE_INVALID;
1284
288
        }
1285
370
        break;
1286
1287
180
    case 5:
1288
180
        msg_name = "Constellation health (GPS)";
1289
180
        unknown = false;
1290
370
        for (n = 0; n < len; n++) {
1291
190
            struct consat_t *csp = &tp->conhealth.sat[n];
1292
190
            struct b_health_t *m = &msg->msg_type.type5.health[n];
1293
1294
190
            csp->ident = m->sat_id;
1295
190
            csp->iodl = m->issue_of_data_link != 0;
1296
190
            csp->health = m->data_health;
1297
190
            csp->snr = (int)(m->cn0 ? (m->cn0 + CNR_OFFSET) : SNR_BAD);
1298
190
            csp->health_en = m->health_enable != 0;
1299
190
            csp->new_data = m->new_nav_data != 0;
1300
190
            csp->los_warning = m->loss_warn != 0;
1301
190
            csp->tou = m->time_unhealthy * TU_SCALE;
1302
190
        }
1303
180
        tp->conhealth.nentries = n;
1304
180
        break;
1305
1306
136
    case 6:
1307
136
        msg_name = "Null frame (GPS)";
1308
136
        unknown = false;
1309
136
        break;
1310
1311
254
    case 7:
1312
254
        msg_name = "Beacon Almanac (GPS)";
1313
254
        unknown = false;
1314
254
        if (ROWS(msg->msg_type.type7.almanac) <= len) {
1315
            // Coverity  645086 Out-of-bounds write
1316
0
            GPSD_LOG(LOG_PROG, &session->context->errout,
1317
0
                     "RTCM2: type 7 bad len %u >= %zu\n",
1318
0
                     len, ROWS(msg->msg_type.type7.almanac));
1319
0
            break;
1320
0
        }
1321
464
        for (w = 0; w < len; w++) {
1322
210
            struct station_t *np = &tp->almanac.station[w];
1323
210
            struct b_station_t *mp = &msg->msg_type.type7.almanac[w];
1324
1325
210
            np->latitude = mp->w3.lat * LA_SCALE;
1326
210
            np->longitude = ((mp->w3.lon_h << 8) | mp->w4.lon_l) * LO_SCALE;
1327
210
            np->range = mp->w4.range;
1328
210
            np->frequency =
1329
210
                (((mp->w4.freq_h << 6) | mp->w5.freq_l) * FREQ_SCALE) +
1330
210
                FREQ_OFFSET;
1331
210
            np->health = mp->w5.health;
1332
210
            np->station_id = mp->w5.station_id,
1333
210
                np->bitrate = tx_speed[mp->w5.bit_rate];
1334
210
        }
1335
254
        tp->almanac.nentries = len / 3;
1336
254
        break;
1337
1338
58
    case 8:
1339
58
        msg_name = "Pseudolite Almanac";
1340
58
        break;
1341
1342
    // case 9 is handled above with case 1
1343
1344
78
    case 10:
1345
78
        msg_name = "P-Code Differential Corrections";
1346
78
        break;
1347
1348
109
    case 11:
1349
109
        msg_name = "C/A Code L2 Corrections";
1350
109
        break;
1351
1352
117
    case 12:
1353
117
        msg_name = "Pseudolite Station Parameters";
1354
117
        break;
1355
1356
187
    case 13:
1357
187
        msg_name = "Ground Transmitter Parameters";
1358
187
        unknown = false;
1359
187
        tp->xmitter.status = (bool)msg->msg_type.type13.w1.status;
1360
187
        tp->xmitter.rangeflag = (bool)msg->msg_type.type13.w1.rangeflag;
1361
187
        tp->xmitter.lat = msg->msg_type.type13.w1.lat * LATLON_SCALE;
1362
187
        tp->xmitter.lon = msg->msg_type.type13.w2.lon * LATLON_SCALE;
1363
187
        tp->xmitter.range = msg->msg_type.type13.w2.range * RANGE_SCALE;
1364
187
        if (0 == tp->xmitter.range) {
1365
154
            tp->xmitter.range = 1024;
1366
154
        }
1367
187
        break;
1368
1369
77
    case 14:
1370
77
        msg_name = "GPS Time Of Week";
1371
77
        unknown = false;
1372
77
        tp->gpstime.week = msg->msg_type.type14.w1.week;
1373
77
        tp->gpstime.hour = msg->msg_type.type14.w1.hour;
1374
77
        tp->gpstime.leapsecs = msg->msg_type.type14.w1.leapsecs;
1375
77
        break;
1376
1377
67
    case 15:
1378
67
        msg_name = "Ionospheric Delay Message";
1379
67
        break;
1380
1381
522
    case 16:
1382
522
        msg_name = "Special Message (GPS)";
1383
522
        unknown = false;
1384
675
        for (w = 0; w < len; w++) {
1385
422
            if (!msg->msg_type.type16.txt[w].byte1) {
1386
111
                break;
1387
111
            }
1388
311
            tp->message[n++] = (char)(msg->msg_type.type16.txt[w].byte1);
1389
311
            if (!msg->msg_type.type16.txt[w].byte2) {
1390
68
                break;
1391
68
            }
1392
243
            tp->message[n++] = (char)(msg->msg_type.type16.txt[w].byte2);
1393
243
            if (!msg->msg_type.type16.txt[w].byte3) {
1394
90
                break;
1395
90
            }
1396
153
            tp->message[n++] = (char)(msg->msg_type.type16.txt[w].byte3);
1397
153
        }
1398
522
        tp->message[n] = '\0';
1399
522
        break;
1400
1401
115
    case 17:
1402
115
        msg_name = "GPS Ephemeris";
1403
115
        break;
1404
1405
289
    case 18:
1406
289
        msg_name = "RTK Uncorrected Carrier-phase";
1407
289
        unknown = false;
1408
        // WIP: partial decode
1409
289
        if (1 > len) {
1410
            // too short
1411
83
            break;
1412
83
        }
1413
206
        {
1414
206
            struct rtcm2_msg18 *m = &msg->msg_type.type18;
1415
206
            tp->rtk.nentries = (len - 1) / 2;
1416
206
            unsigned i;
1417
1418
206
            tp->rtk.tom = m->tom;
1419
206
            tp->rtk.f = m->f;
1420
617
            for (i = 0; i < tp->rtk.nentries; i++) {
1421
411
                tp->rtk.sat[i].m = m->sat[i].m;
1422
411
                tp->rtk.sat[i].pc = m->sat[i].pc;
1423
411
                tp->rtk.sat[i].g = m->sat[i].g;
1424
411
                tp->rtk.sat[i].ident = m->sat[i].ident;
1425
411
                tp->rtk.sat[i].dq = m->sat[i].dq;
1426
411
                tp->rtk.sat[i].carrier_phase = m->sat[i].cp_l;
1427
411
                tp->rtk.sat[i].carrier_phase |= m->sat[i].cp_h << 24;
1428
411
                tp->rtk.sat[i].clc = m->sat[i].clc;
1429
411
            }
1430
206
        }
1431
206
        break;
1432
1433
147
    case 19:
1434
147
        msg_name = "RTK Corrected Pseudorange";
1435
        // WIP: partial decode
1436
147
        if (1 > len) {
1437
            // too short
1438
44
            break;
1439
44
        }
1440
103
        {
1441
103
            struct rtcm2_msg19 *m = &msg->msg_type.type19;
1442
103
            unsigned i;
1443
103
            tp->rtk.tom = m->tom;
1444
103
            tp->rtk.f = m->f;
1445
103
            tp->rtk.sm = m->sm;
1446
103
            tp->rtk.nentries = (len - 1) / 2;
1447
1448
143
            for (i = 0; i < tp->rtk.nentries; i++) {
1449
40
                tp->rtk.sat[i].m = m->sat[i].m;
1450
40
                tp->rtk.sat[i].pc = m->sat[i].pc;
1451
40
                tp->rtk.sat[i].g = m->sat[i].g;
1452
40
                tp->rtk.sat[i].ident = m->sat[i].ident;
1453
40
                tp->rtk.sat[i].dq = m->sat[i].dq;
1454
40
                tp->rtk.sat[i].pseudorange = m->sat[i].pr_l;
1455
40
                tp->rtk.sat[i].pseudorange |= m->sat[i].pr_h << 24;
1456
40
            }
1457
103
        }
1458
103
        break;
1459
1460
93
    case 20:
1461
93
        msg_name = "RTK Carrier Phase Corrections";
1462
        // WIP: partial decode
1463
93
        if (3 > len) {
1464
            // too short
1465
35
            break;
1466
35
        }
1467
58
        {
1468
58
            struct rtcm2_msg20 *m = &msg->msg_type.type20;
1469
58
            tp->rtk.tom = m->tom;
1470
58
            tp->rtk.f = m->f;
1471
58
        }
1472
58
        break;
1473
1474
182
    case 21:
1475
182
        msg_name = "High-Accuracy Pseudorange Corrections";
1476
        // WIP: partial decode
1477
182
        if (3 > len) {
1478
            // too short
1479
100
            break;
1480
100
        }
1481
82
        {
1482
82
            struct rtcm2_msg21 *m = &msg->msg_type.type21;
1483
82
            tp->rtk.tom = m->tom;
1484
82
            tp->rtk.f = m->f;
1485
82
            tp->rtk.sm = m->sm;
1486
82
        }
1487
82
        break;
1488
1489
506
    case 22:
1490
        // Extends types 3 and 34
1491
506
        msg_name = "Extended Reference Station Parameters";
1492
506
        unknown = false;
1493
        // WIP: partial decode
1494
506
        if (3 > len) {
1495
            // too short
1496
282
            break;
1497
282
        }
1498
        // May be length 3, 4 or 5!
1499
224
        {
1500
224
            struct rtcm2_msg22 *m = &msg->msg_type.type22;
1501
1502
224
            tp->ref_sta.dx = m->ecef_dx * EDXYZ_SCALE;
1503
224
            tp->ref_sta.dy = m->ecef_dy * EDXYZ_SCALE;
1504
224
            tp->ref_sta.dz = m->ecef_dz * EDXYZ_SCALE;
1505
224
            if (3 < len) {
1506
                // word 4 present
1507
155
                tp->ref_sta.gs = m->gs;
1508
155
                if (0 == m->nh) {
1509
82
                    tp->ref_sta.ah = m->ah * EDXYZ_SCALE;
1510
82
                }
1511
155
            }
1512
224
            if (4 < len) {
1513
                // word 5 present
1514
84
                tp->ref_sta.dx2 = m->ecef_dx2 * EDXYZ2_SCALE;
1515
84
                tp->ref_sta.dy2 = m->ecef_dy2 * EDXYZ2_SCALE;
1516
84
                tp->ref_sta.dz2 = m->ecef_dz2 * EDXYZ2_SCALE;
1517
84
            }
1518
224
        }
1519
224
        break;
1520
1521
186
    case 23:
1522
186
        msg_name = "Antenna Type Definition";
1523
        // WIP
1524
186
        unknown = false;
1525
186
        if (1 > len) {
1526
            // too short
1527
49
            break;
1528
49
        }
1529
137
        {
1530
137
            unsigned sf;
1531
137
            unsigned nad = 0, nas = 0;
1532
137
            unsigned char tbuf[RTCM2_WORDS_MAX * 3];
1533
137
            struct rtcm2_msg23 *m = &msg->msg_type.type23;
1534
137
            unsigned i = 0, j = 0;
1535
1536
137
            tp->ref_sta.ar = (m->words[0].byte0 >> 6) & 1;
1537
            // sf, serial flag.  serial number to follow?
1538
137
            sf = (m->words[0].byte0 >> 5) & 1;
1539
            // nad, number of characters for antenna description, is 0 to 31
1540
137
            nad = m->words[0].byte0 & 0x1f;
1541
1542
137
            if (sizeof(tbuf) < ((size_t)len * 3)) {
1543
0
                GPSD_LOG(LOG_ERROR, &session->context->errout,
1544
0
                         "RTCM2: len too long, len %u nad %d\n",
1545
0
                         len, nad);
1546
0
                break;
1547
0
            }
1548
            // crazy packing...  move to simple array first
1549
137
            memset(tbuf, 0, sizeof(tbuf));   // avoid a CVE
1550
334
            for (i = 0; i < len; i++) {
1551
197
                tbuf[j++] = m->words[i].byte0;
1552
197
                tbuf[j++] = m->words[i].byte1;
1553
197
                tbuf[j++] = m->words[i].byte2;
1554
197
            }
1555
#ifdef __UNUSED__
1556
            // debug code
1557
            {
1558
                char tmpbuf[100];
1559
                GPSD_LOG(LOG_SHOUT, &session->context->errout,
1560
                         "RTCM2: len %u nad %d tbuf %s\n",
1561
                         len, nad,
1562
                         gps_hexdump(tmpbuf, sizeof(tmpbuf),
1563
                                     (char *)tbuf, len * 3));
1564
            }
1565
#endif // __UNUSED__
1566
            // skip first byte (AR, SF, NAD)
1567
137
            memcpy(tp->ref_sta.ant_desc, &tbuf[1], nad);
1568
137
            tp->ref_sta.ant_desc[nad] = '\0';
1569
1570
137
            tp->ref_sta.setup_id = tbuf[nad + 1];
1571
1572
            // get serial number
1573
137
            if (1 == sf) {
1574
                // nas is 0 to 31. just after last ant desc byte
1575
78
                nas = tbuf[nad + 2] & 0x1f;
1576
78
                memcpy(tp->ref_sta.ant_serial, &tbuf[nad + 3], nas);
1577
78
            }
1578
137
            tp->ref_sta.ant_serial[nas] = '\0';
1579
137
        }
1580
0
        break;
1581
1582
189
    case 24:
1583
189
        msg_name = "Antenna Reference Point (arp)";
1584
        // WIP
1585
189
        unknown = false;
1586
189
        {
1587
189
            struct rtcm2_msg24 *m = &msg->msg_type.type24;
1588
            // try to prevent int overflow
1589
189
            long long temp;
1590
1591
189
            temp = ((long long)m->w3.x_h << 8) | (m->w4.x_l);
1592
189
            tp->ref_sta.x = temp * EXYZ_SCALE;
1593
189
            temp = ((long long)m->w4.y_h << 32) |
1594
189
                    (m->w5.y_m << 6) |
1595
189
                    (m->w6.y_l);
1596
189
            tp->ref_sta.y = temp * EXYZ_SCALE;
1597
189
            temp = ((long long)m->w6.z_h << 22) | (m->w7.z_l);
1598
189
            tp->ref_sta.z = temp * EXYZ_SCALE;
1599
189
            if (0 == m->w7.ah) {
1600
120
                tp->ref_sta.ah = m->w8.ah * EDXYZ_SCALE;
1601
120
            }
1602
189
        }
1603
189
        break;
1604
1605
63
    case 25:
1606
63
        FALLTHROUGH
1607
131
    case 26:
1608
131
        msg_name = "Undefined";
1609
131
        break;
1610
1611
75
    case 27:
1612
75
        msg_name = "Radio Beacon Almanac";
1613
75
        break;
1614
1615
66
    case 28:
1616
66
        FALLTHROUGH
1617
129
    case 29:
1618
129
        FALLTHROUGH
1619
228
    case 30:
1620
228
        msg_name = "Undefined";
1621
228
        break;
1622
1623
67
    case 31:
1624
67
        FALLTHROUGH
1625
226
    case 34:
1626
226
    {
1627
226
        int lens = (int)len;
1628
        // 32 and 34 are the same, except 31 is all sats, 34 is some sats
1629
226
        struct glonass_correction_t *m = &msg->msg_type.type31.corrections[0];
1630
226
        msg_name = "Differential GLONASS corrections";
1631
226
        unknown = false;
1632
1633
525
        while (0 <= lens) {
1634
299
            if (2 <= lens) {
1635
172
                tp->glonass_ranges.sat[n].ident = m->w3.satident1;
1636
172
                tp->glonass_ranges.sat[n].udre = m->w3.udre1;
1637
172
                tp->glonass_ranges.sat[n].change = (bool)m->w4.change1;
1638
172
                tp->glonass_ranges.sat[n].tod = m->w4.tod1;
1639
172
                tp->glonass_ranges.sat[n].prc = m->w3.prc1 *
1640
172
                    (m->w3.scale1 ? PRCLARGE : PRCSMALL);
1641
172
                tp->glonass_ranges.sat[n].rrc = m->w4.rrc1 *
1642
172
                    (m->w3.scale1 ? RRLARGE : RRSMALL);
1643
172
                n++;
1644
172
            }
1645
299
            if (4 <= lens) {
1646
83
                tp->glonass_ranges.sat[n].ident = m->w4.satident2;
1647
83
                tp->glonass_ranges.sat[n].udre = m->w4.udre2;
1648
83
                tp->glonass_ranges.sat[n].change = (bool)m->w6.change2;
1649
83
                tp->glonass_ranges.sat[n].tod = m->w6.tod2;
1650
83
                tp->glonass_ranges.sat[n].prc = m->w5.prc2 *
1651
83
                    (m->w4.scale2 ? PRCLARGE : PRCSMALL);
1652
83
                tp->glonass_ranges.sat[n].rrc = m->w5.rrc2 *
1653
83
                    (m->w4.scale2 ? RRLARGE : RRSMALL);
1654
83
                n++;
1655
83
            }
1656
299
            if (5 <= lens) {
1657
73
                tp->glonass_ranges.sat[n].ident = m->w6.satident3;
1658
73
                tp->glonass_ranges.sat[n].udre = m->w6.udre3;
1659
73
                tp->glonass_ranges.sat[n].change = (bool)m->w7.change3;
1660
73
                tp->glonass_ranges.sat[n].tod = m->w7.tod3;
1661
73
                tp->glonass_ranges.sat[n].prc =
1662
73
                    ((m->w6.prc3_h << 8) | (m->w7.prc3_l)) *
1663
73
                    (m->w6.scale3 ? PRCLARGE : PRCSMALL);
1664
73
                tp->glonass_ranges.sat[n].rrc =
1665
73
                    m->w7.rrc3 * (m->w6.scale3 ? RRLARGE : RRSMALL);
1666
73
                n++;
1667
73
            }
1668
299
            lens -= 5;
1669
299
            m++;
1670
299
        }
1671
226
        tp->glonass_ranges.nentries = n;
1672
226
    }
1673
226
        break;
1674
1675
111
    case 32:
1676
111
        msg_name = "Reference Station Parameters (GLONASS)";
1677
111
        break;
1678
1679
80
    case 33:
1680
80
        msg_name = "Constellation health (GLONASS)";
1681
80
        break;
1682
1683
    // case 34 is above with 31
1684
1685
61
    case 35:
1686
61
        msg_name = "Beacon Almanac (GLONASS)";
1687
61
        break;
1688
1689
72
    case 36:
1690
72
        msg_name = "Special Message (GLONASS)";
1691
72
        break;
1692
1693
66
    case 37:
1694
66
        msg_name = "GNSS System Time Offset";
1695
66
        break;
1696
1697
80
    case 59:
1698
80
        msg_name = "Proprietary Message";
1699
80
        break;
1700
1701
79
    default:
1702
79
        msg_name = "Huh?";
1703
79
        break;
1704
5.66k
    }
1705
1706
5.66k
    if (unknown) {
1707
2.03k
        memcpy(tp->words, msg->msg_type.rtcm2_msgunk,
1708
2.03k
               tp->length * sizeof(isgps30bits_t));
1709
2.03k
        if (NULL == msg_name) {
1710
0
            GPSD_LOG(LOG_PROG, &session->context->errout,
1711
0
                     "RTCM2: type %d (unknown), length %d\n",
1712
0
                     tp->type, tp->length + 2);
1713
2.03k
        } else {
1714
2.03k
            GPSD_LOG(LOG_PROG, &session->context->errout,
1715
2.03k
                     "RTCM2: type %d (%s), length %d\n",
1716
2.03k
                     tp->type, msg_name,tp->length + 2);
1717
2.03k
        }
1718
3.63k
    } else {
1719
3.63k
        GPSD_LOG(LOG_PROG, &session->context->errout,
1720
3.63k
                 "RTCM2: type %d (%s), length %d\n",
1721
3.63k
                 tp->type, msg_name, tp->length + 2);
1722
3.63k
    }
1723
5.66k
    GPSD_LOG(LOG_RAW, &session->context->errout,
1724
5.66k
             "RTCM 2: type %d (%s) length %d words "
1725
5.66k
             "from %zd bytes: %s\n",
1726
5.66k
             tp->type,
1727
5.66k
             msg_name,
1728
5.66k
             tp->length + 2,
1729
5.66k
             session->lexer.isgps.buflen,
1730
5.66k
             gps_hexdump(session->msgbuf, sizeof(session->msgbuf),
1731
5.66k
                         (unsigned char *)session->lexer.isgps.buf,
1732
5.66k
                         (tp->length + 2) * sizeof(isgps30bits_t)));
1733
5.66k
}
1734
1735
static bool preamble_match(isgps30bits_t * w)
1736
621M
{
1737
621M
    return (((struct rtcm2_msghw1 *)w)->preamble == PREAMBLE_PATTERN);
1738
621M
}
1739
1740
static bool length_check(struct gps_lexer_t *lexer)
1741
25.3k
{
1742
25.3k
    return lexer->isgps.bufindex >= 2
1743
17.1k
        && lexer->isgps.bufindex >=
1744
17.1k
        ((struct rtcm2_msg_t *)lexer->isgps.buf)->w2.frmlen + 2u;
1745
25.3k
}
1746
1747
enum isgpsstat_t rtcm2_decode(struct gps_lexer_t *lexer, unsigned int c)
1748
109M
{
1749
109M
    return isgps_decode(lexer,
1750
109M
                        preamble_match, length_check, RTCM2_WORDS_MAX, c);
1751
109M
}
1752
1753
// vim: set expandtab shiftwidth=4