Coverage Report

Created: 2026-07-16 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_rtcm3.c
Line
Count
Source
1
/*****************************************************************************
2
3
This is a decoder for RTCM-104 3.x, a serial protocol used for
4
broadcasting pseudorange corrections from differential-GPS reference
5
stations.  The applicable specification is RTCM 10403.1: RTCM Paper
6
177-2006-SC104-STD.  This obsolesces the earlier RTCM-104 2.x
7
specifications. The specification document is proprietary; ordering
8
instructions are accessible from <http://www.rtcm.org/>
9
under "Publications".
10
11
Unike the RTCM 2.x protocol, RTCM3.x does not use the strange
12
sliding-bit-window IS-GPS-200 protocol as a transport layer, but is a
13
self-contained byte-oriented packet protocol.  Packet recognition is
14
handled in the GPSD packet-getter state machine; this code is
15
concerned with unpacking the packets into well-behaved C structures,
16
coping with odd field lengths and fields that may overlap byte
17
boundaries.  These report structures live in gps.h.
18
19
Note that the unpacking this module does is probably useful only for
20
RTCM reporting and diagnostic tools.  It is not necessary when
21
passing RTCM corrections to a GPS, which normally should just be
22
passed an entire correction packet for processing by their internal
23
firmware.
24
25
Decodes of the following types have been verified: 1004, 1005, 1006,
26
1008, 1012, 1013, 1029. There is good reason to believe the 1007 code
27
is correct, as it's identical to 1008 up to where it ends.
28
29
The 1033 decode was arrived at by looking at an rtcminspect dump and noting
30
that it carries an information superset of the 1008.  There are additional
31
Receiver and Firmware fields we're not certain to decode without access
32
to an RTCM3 standard at revision 4 or later, but the guess in the code
33
has been observed to correctly analyze a message with a nonempty Receiver
34
field.
35
36
This file is Copyright 2010 by the GPSD project
37
SPDX-License-Identifier: BSD-2-clause
38
39
*****************************************************************************/
40
41
#include "../include/gpsd_config.h"  // must be before all includes
42
43
#include <string.h>
44
45
#include "../include/gpsd.h"
46
#include "../include/bits.h"
47
48
// scaling constants for RTCM3 real number types
49
1.76k
#define GPS_PSEUDORANGE_RESOLUTION      0.02    // DF011
50
2.87k
#define PSEUDORANGE_DIFF_RESOLUTION     0.0005  // DF012, DF042
51
1.54k
#define CARRIER_NOISE_RATIO_UNITS       0.25    // DF015, DF045, DF050
52
470
#define ANTENNA_POSITION_RESOLUTION     0.0001  // DF025, DF026, DF027
53
1.03k
#define GLONASS_PSEUDORANGE_RESOLUTION  0.02    // DF041
54
2
#define ANTENNA_DEGREE_RESOLUTION       25e-6   // DF062
55
#define GPS_EPOCH_TIME_RESOLUTION       0.1     // DF065
56
// DF069, DF070, DF192, DF193, DF194, DF195
57
24
#define PHASE_CORRECTION_RESOLUTION     0.5
58
// DF156, DF157, DF158, DF166, DF167, DF168, DF169, DF196, DF197
59
207
#define TRANSLATION_MM_RESOLUTION       0.001
60
52
#define VALIDITY_RESOLUTION             2.0     // DF152, DF153, DF154, DF155
61
17
#define SCALE_PPM_RESOLUTION            1e-5    // DF162
62
39
#define ROTATION_ARCSEC_RESOLUTION      2e-5    // DF159, DF160, DF161
63
// DF171, DF172, DF176, DF177, DF178, DF179, DF183, DF184, DF185, DF186
64
8
#define PROJ_ORIGIN_RESOLUTION          11e-9
65
115
#define DEG_ARCSEC_RESOLUTION           3600
66
6
#define CM_RESOLUTION                   0.01    // DF198
67
192
#define RES_ARCSEC_RESOLUTION           3e-5    // DF199, DF200
68
69
// Other magic values
70
4.69k
#define GPS_INVALID_PSEUDORANGE         0x80000 // DF012, DF018
71
162
#define GLONASS_INVALID_RANGEINCR       0x2000  // DF047
72
885
#define GLONASS_CHANNEL_BASE            7       // DF040
73
74
// Large case statements make GNU indent very confused
75
// *INDENT-OFF*
76
77
/* good source on message types:
78
 * https://software.rtcm-ntrip.org/export/HEAD/ntrip/trunk/BNC/src/bnchelp.html
79
 * Also look in the BNC source
80
 * and look at the tklib source: http://www.rtklib.com/
81
 */
82
83
31.7k
#define ugrab(width)    (bitcount += width, ubits(buf, \
84
31.7k
                         bitcount - width, width, false))
85
9.41k
#define sgrab(width)    (bitcount += width, sbits(buf,  \
86
9.41k
                         bitcount - width, width, false))
87
88
/* copy strings safely.
89
 * RTCM 3.3 says most strings are 31 chars, or less, of ISO 8859-1
90
 * but 1007 says DF030 is 20 chars, or less, of ASCII
91
 * and 1029 DF140 is 255 bytes, or less, of UTF-8
92
 */
93
static void rtcm3_copy_string_field(char *dst, size_t dstlen,
94
                                    const unsigned char *src, size_t srclen)
95
375
{
96
375
    if (0 == dstlen) {
97
0
        return;
98
0
    }
99
375
    if (srclen >= dstlen) {
100
21
        srclen = dstlen - 1;
101
21
    }
102
375
    (void)memcpy(dst, src, srclen);
103
375
    dst[srclen] = '\0';
104
375
}
105
106
/* decode 1015/1016/1017 header
107
 * they share a common header
108
 * TODO: rtklib has C code for these.
109
 *
110
 * Return: false if decoded
111
 *         true if runt
112
 */
113
static bool rtcm3_101567(const struct gps_context_t *context,
114
                         struct rtcm3_t *rtcm, const unsigned char *buf)
115
19
{
116
19
    int bitcount = 36;  // 8 preamble, 6 zero, 10 length, 12 type
117
118
    // 1015, 1016, and 1017 all use the 1015 struct
119
19
    rtcm->rtcmtypes.rtcm3_1015.header.network_id = ugrab(12);
120
19
    rtcm->rtcmtypes.rtcm3_1015.header.subnetwork_id = ugrab(4);
121
19
    rtcm->rtcmtypes.rtcm3_1015.header.tow = ugrab(23);
122
19
    rtcm->rtcmtypes.rtcm3_1015.header.multimesg = (bool)ugrab(1);
123
19
    rtcm->rtcmtypes.rtcm3_1015.header.master_id = ugrab(12);
124
19
    rtcm->rtcmtypes.rtcm3_1015.header.aux_id = ugrab(12);
125
19
    rtcm->rtcmtypes.rtcm3_1015.header.satcount = ugrab(4);
126
127
19
    GPSD_LOG(LOG_PROG, &context->errout, "RTCM3: rtcm3_10567(%u) "
128
19
             "network_id %u subnetwork_id %u tow %lu multimesg %u "
129
19
             "master_id %u aux_id %u satcount %u",
130
19
             rtcm->type,
131
19
             rtcm->rtcmtypes.rtcm3_1015.header.network_id,
132
19
             rtcm->rtcmtypes.rtcm3_1015.header.subnetwork_id,
133
19
             rtcm->rtcmtypes.rtcm3_1015.header.tow,
134
19
             rtcm->rtcmtypes.rtcm3_1015.header.multimesg,
135
19
             rtcm->rtcmtypes.rtcm3_1015.header.master_id,
136
19
             rtcm->rtcmtypes.rtcm3_1015.header.aux_id,
137
19
             rtcm->rtcmtypes.rtcm3_1015.header.satcount);
138
19
    return false;
139
19
}
140
141
/* decode 4076 header
142
 * IGS State Space Representation (SSR) Format
143
 * www.igs.org
144
 * https://files.igs.org/pub/data/format/igs_ssr_v1.pdf
145
 *
146
 * Return: false if decoded
147
 *         true if runt or undecoded
148
 */
149
static bool rtcm3_4076(const struct gps_context_t *context,
150
                         struct rtcm3_t *rtcm, const unsigned char *buf)
151
1
{
152
1
    int bitcount = 36;         // 8 preamble, 6 zero, 10 length, 12 type
153
154
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_vers = ugrab(3);
155
1
    rtcm->rtcmtypes.rtcm3_4076.igs_num = ugrab(8);
156
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_epoch = ugrab(20);
157
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_update = ugrab(4);
158
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_mmi = ugrab(1);
159
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_iod = ugrab(4);
160
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_provider = ugrab(16);
161
1
    rtcm->rtcmtypes.rtcm3_4076.ssr_solution = ugrab(4);
162
163
1
    GPSD_LOG(LOG_PROG, &context->errout,
164
1
             "RTCM3: rtcm3_4076 ver %u igs_num %u Epoch %u update %u mmi %u "
165
1
             "IOD %u Provider %u Solution %u\n",
166
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_vers,
167
1
             rtcm->rtcmtypes.rtcm3_4076.igs_num,
168
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_epoch,
169
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_update,
170
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_mmi,
171
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_iod,
172
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_provider,
173
1
             rtcm->rtcmtypes.rtcm3_4076.ssr_solution);
174
1
    return true;
175
1
}
176
177
/* decode MSM header
178
 * MSM1 to MSM7 share a common header
179
 * TODO: rtklib has C code for these.
180
 *
181
 * Return: false if decoded
182
 *         true if runt, or error
183
 */
184
static bool rtcm3_decode_msm(const struct gps_context_t *context,
185
                             struct rtcm3_t *rtcm, const unsigned char *buf)
186
185
{
187
185
    int bitcount = 36;  // 8 preamble, 6 zero, 10 length, 12 type
188
185
    unsigned n_sig = 0, n_sat = 0, n_cell = 0;
189
185
    uint64_t sat_mask;
190
185
    uint32_t sig_mask;
191
185
    unsigned i;
192
193
185
    if (22 > rtcm->length) {
194
        // need 169 bits, 21.125 bytes
195
48
        rtcm->length = 0;          // set to zero to prevent JSON decode
196
48
        GPSD_LOG(LOG_WARN, &context->errout,
197
48
                 "RTCM3: rtcm3_decode_msm() type %d runt length %u ",
198
48
                 rtcm->type, rtcm->length);
199
48
        return true;
200
48
    }
201
202
137
    rtcm->rtcmtypes.rtcm3_msm.station_id = ugrab(12);
203
137
    rtcm->rtcmtypes.rtcm3_msm.tow = ugrab(30);
204
137
    rtcm->rtcmtypes.rtcm3_msm.sync = ugrab(1);
205
137
    rtcm->rtcmtypes.rtcm3_msm.IODS = ugrab(3);
206
137
    bitcount += 7;             // skip 7 reserved bits, DF001
207
137
    rtcm->rtcmtypes.rtcm3_msm.steering = ugrab(2);
208
137
    rtcm->rtcmtypes.rtcm3_msm.ext_clk = ugrab(2);
209
137
    rtcm->rtcmtypes.rtcm3_msm.smoothing = ugrab(1);
210
137
    rtcm->rtcmtypes.rtcm3_msm.interval = ugrab(3);
211
    // FIXME: rtcm->rtcmtypes.rtcm3_msm.sat_mask = ugrab(64);
212
    // ugrab(56) is max, can't do 64, so stack it
213
137
    rtcm->rtcmtypes.rtcm3_msm.sat_mask = ugrab(32) << 32;
214
137
    rtcm->rtcmtypes.rtcm3_msm.sat_mask |= ugrab(32);
215
137
    rtcm->rtcmtypes.rtcm3_msm.sig_mask = ugrab(32);
216
217
    // count satellites
218
137
    sat_mask = rtcm->rtcmtypes.rtcm3_msm.sat_mask;
219
7.66k
    while (sat_mask) {
220
7.52k
        n_sat += sat_mask & 1;
221
7.52k
        sat_mask >>= 1;
222
7.52k
    }
223
    // count signals
224
137
    sig_mask = rtcm->rtcmtypes.rtcm3_msm.sig_mask;
225
3.53k
    while (sig_mask) {
226
3.39k
        n_sig += sig_mask & 1;
227
3.39k
        sig_mask >>= 1;
228
3.39k
    }
229
    // determine cells
230
137
    n_cell = n_sat * n_sig;
231
137
    rtcm->rtcmtypes.rtcm3_msm.n_sat = n_sat;
232
137
    rtcm->rtcmtypes.rtcm3_msm.n_sig = n_sig;
233
137
    rtcm->rtcmtypes.rtcm3_msm.n_cell = n_cell;
234
235
137
    if (0 == n_sat ||
236
136
        RTCM3_MAX_SATELLITES < n_sat ||
237
136
        RTCM3_MAX_SATELLITES < n_cell) {
238
85
        GPSD_LOG(LOG_WARN, &context->errout,
239
85
                 "RTCM3: rtcm3_decode_msm(%u) interval %u  sat_mask x%llx "
240
85
                 "sig_mask x%x invalid n_cell %u\n",
241
85
                 rtcm->type,
242
85
                 rtcm->rtcmtypes.rtcm3_msm.interval,
243
85
                 (unsigned long long)rtcm->rtcmtypes.rtcm3_msm.sat_mask,
244
85
                 rtcm->rtcmtypes.rtcm3_msm.sig_mask,
245
85
                 n_cell);
246
85
        return false;
247
85
    }
248
249
    // cell_mask is variable length!  ugrab() width max is 56
250
52
    if (56 >= n_cell) {
251
42
        rtcm->rtcmtypes.rtcm3_msm.cell_mask = ugrab(n_cell);
252
42
    } else {
253
        // 57 to 64, breaks ugrab(), workaround it...
254
10
        rtcm->rtcmtypes.rtcm3_msm.cell_mask = ugrab(56);
255
10
        rtcm->rtcmtypes.rtcm3_msm.cell_mask <<= n_cell - 56;
256
10
        rtcm->rtcmtypes.rtcm3_msm.cell_mask |= ugrab(n_cell - 56);
257
10
    }
258
259
    // Decode Satellite Data
260
261
    // Decode DF397 (MSM 4-7)
262
52
    if (4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
263
46
        5 == rtcm->rtcmtypes.rtcm3_msm.msm ||
264
32
        6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
265
36
        7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
266
606
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_sat; i++) {
267
570
            rtcm->rtcmtypes.rtcm3_msm.sat[i].rr_ms = ugrab(8);
268
570
        }
269
36
    }
270
271
    // Decode Extended Info (MSM 5+7)
272
52
    if (5 == rtcm->rtcmtypes.rtcm3_msm.msm ||
273
38
        7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
274
447
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_sat; i++) {
275
423
            rtcm->rtcmtypes.rtcm3_msm.sat[i].ext_info = ugrab(4);
276
423
        }
277
24
    }
278
279
    // Decode DF398 (MSM 1-7)
280
806
    for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_sat; i++) {
281
754
        rtcm->rtcmtypes.rtcm3_msm.sat[i].rr_m1 = ugrab(10);
282
754
    };
283
284
    // Decode DF399 (MSM 5+7)
285
52
    if (5 == rtcm->rtcmtypes.rtcm3_msm.msm ||
286
38
        7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
287
447
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_sat; i++) {
288
423
            rtcm->rtcmtypes.rtcm3_msm.sat[i].rates_rphr = ugrab(14);
289
423
        }
290
24
    }
291
292
    // Decode Signal Data
293
294
    // Decode DF400 (MSM 1,3,4,5) resp. DF405 (MSM 6+7)
295
52
    if (1 == rtcm->rtcmtypes.rtcm3_msm.msm ||
296
49
        3 == rtcm->rtcmtypes.rtcm3_msm.msm ||
297
43
        4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
298
37
        5 == rtcm->rtcmtypes.rtcm3_msm.msm) {
299
894
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
300
865
            rtcm->rtcmtypes.rtcm3_msm.sig[i].pseudo_r = sgrab(15);
301
865
        }
302
29
    } else if (6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
303
17
               7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
304
307
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
305
291
            rtcm->rtcmtypes.rtcm3_msm.sig[i].pseudo_r = sgrab(20);
306
291
        }
307
16
    }
308
309
    // Decode DF401 (MSM 2,3,4,5) resp. DF406 (MSM 6+7)
310
52
    if (2 == rtcm->rtcmtypes.rtcm3_msm.msm ||
311
45
        3 == rtcm->rtcmtypes.rtcm3_msm.msm ||
312
39
        4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
313
33
        5 == rtcm->rtcmtypes.rtcm3_msm.msm) {
314
918
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
315
885
            rtcm->rtcmtypes.rtcm3_msm.sig[i].phase_r = sgrab(22);
316
885
        }
317
33
    } else if (6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
318
16
               7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
319
307
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
320
291
            rtcm->rtcmtypes.rtcm3_msm.sig[i].phase_r = sgrab(24);
321
291
        }
322
16
    }
323
324
    // Decode DF402 (MSM 2,3,4,5) resp. DF407 (MSM 6+7)
325
52
    if (2 == rtcm->rtcmtypes.rtcm3_msm.msm ||
326
45
        3 == rtcm->rtcmtypes.rtcm3_msm.msm ||
327
39
        4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
328
33
        5 == rtcm->rtcmtypes.rtcm3_msm.msm) {
329
918
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
330
885
            rtcm->rtcmtypes.rtcm3_msm.sig[i].lti = ugrab(4);
331
885
        }
332
33
    } else if (6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
333
16
               7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
334
307
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
335
291
            rtcm->rtcmtypes.rtcm3_msm.sig[i].lti = ugrab(10);
336
291
        }
337
16
    }
338
339
    // Decode DF420 (MSM 2-7)
340
52
    if (2 == rtcm->rtcmtypes.rtcm3_msm.msm ||
341
45
        3 == rtcm->rtcmtypes.rtcm3_msm.msm ||
342
39
        4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
343
33
        5 == rtcm->rtcmtypes.rtcm3_msm.msm ||
344
19
        6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
345
49
        7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
346
1.22k
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
347
1.17k
            rtcm->rtcmtypes.rtcm3_msm.sig[i].half_amb = ugrab(1);
348
1.17k
        }
349
49
    }
350
351
    // Decode DF403 (MSM 4+5) resp. DF408 (MSM 6+7)
352
52
    if (4 == rtcm->rtcmtypes.rtcm3_msm.msm ||
353
46
        5 == rtcm->rtcmtypes.rtcm3_msm.msm) {
354
568
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
355
548
            rtcm->rtcmtypes.rtcm3_msm.sig[i].cnr = ugrab(6);
356
548
        }
357
32
    } else if (6 == rtcm->rtcmtypes.rtcm3_msm.msm ||
358
26
               7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
359
307
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
360
291
            rtcm->rtcmtypes.rtcm3_msm.sig[i].cnr = ugrab(10);
361
291
        }
362
16
    }
363
364
    // Decode DF404 (MSM 5+7)
365
52
    if (5 == rtcm->rtcmtypes.rtcm3_msm.msm ||
366
38
        7 == rtcm->rtcmtypes.rtcm3_msm.msm) {
367
649
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_msm.n_cell; i++) {
368
625
            rtcm->rtcmtypes.rtcm3_msm.sig[i].cnr = sgrab(15);
369
625
        }
370
24
    }
371
372
    // tow is %llu for 32-bit compatibility
373
52
    GPSD_LOG(LOG_PROG, &context->errout, "RTCM3: rtcm3_decode_msm(%u) "
374
52
             "gnssid %u MSM%u id %u tow %llu sync %u IODS %u "
375
52
             "steering %u ext_clk %u smoothing %u interval %u "
376
52
             "sat_mask x%llx sig_mask x%lx cell_mask %llx\n",
377
52
             rtcm->type,
378
52
             rtcm->rtcmtypes.rtcm3_msm.gnssid,
379
52
             rtcm->rtcmtypes.rtcm3_msm.msm,
380
52
             rtcm->rtcmtypes.rtcm3_msm.station_id,
381
52
             (unsigned long long)rtcm->rtcmtypes.rtcm3_msm.tow,
382
52
             rtcm->rtcmtypes.rtcm3_msm.sync,
383
52
             rtcm->rtcmtypes.rtcm3_msm.IODS,
384
52
             rtcm->rtcmtypes.rtcm3_msm.steering,
385
52
             rtcm->rtcmtypes.rtcm3_msm.ext_clk,
386
52
             rtcm->rtcmtypes.rtcm3_msm.smoothing,
387
52
             rtcm->rtcmtypes.rtcm3_msm.interval,
388
52
             (long long unsigned)rtcm->rtcmtypes.rtcm3_msm.sat_mask,
389
52
             (long unsigned)rtcm->rtcmtypes.rtcm3_msm.sig_mask,
390
52
             (long long unsigned)rtcm->rtcmtypes.rtcm3_msm.cell_mask);
391
52
    return false;
392
137
}
393
394
/* break out the raw bits into the scaled report-structure fields
395
 *
396
 * Return: void
397
 */
398
void rtcm3_unpack(const struct gps_context_t *context,
399
                  struct rtcm3_t *rtcm, const unsigned char *buf)
400
2.36k
{
401
2.36k
    unsigned n, n2, n3, n4;
402
2.36k
    int bitcount = 0;
403
2.36k
    unsigned i;
404
2.36k
    long temp;
405
2.36k
    bool unknown = true;               // we don't know how to decode
406
2.36k
    const char *msg_name = "Unknown";  // we know the name
407
2.36k
    unsigned preamble, mbz;            // preamble 0xd3, and must be zero
408
2.36k
    unsigned bad_len = 0;
409
410
2.36k
#define GPS_PSEUDORANGE(fld, len) \
411
2.36k
    {temp = ugrab(len);                         \
412
1.82k
    if (temp == GPS_INVALID_PSEUDORANGE) {      \
413
58
        fld.pseudorange = 0;                    \
414
1.76k
    } else {                                    \
415
1.76k
        fld.pseudorange = temp * GPS_PSEUDORANGE_RESOLUTION;} \
416
1.82k
    }
417
2.36k
#define RANGEDIFF(fld, len) \
418
2.49k
    temp = (long)sgrab(len);                    \
419
2.49k
    if (temp == GPS_INVALID_PSEUDORANGE) {      \
420
0
        fld.rangediff = 0;                      \
421
2.49k
    } else {                                    \
422
2.49k
        fld.rangediff = temp * PSEUDORANGE_DIFF_RESOLUTION; \
423
2.49k
    }
424
425
2.36k
    memset(rtcm, 0, sizeof(struct rtcm3_t));
426
427
    // check preamble and zero bits
428
2.36k
    preamble = ugrab(8);
429
2.36k
    mbz = ugrab(6);
430
2.36k
    if (0xD3 != preamble ||
431
1.72k
        0 != mbz) {
432
        // The mbz may eventually used for RTCM version.
433
638
        GPSD_LOG(LOG_WARN, &context->errout,
434
638
                 "RTCM3: invalid preamble x%2x or mbz x%x\n",
435
638
                 preamble, mbz);
436
638
        return;
437
638
    }
438
439
1.72k
    rtcm->length = ugrab(10);
440
1.72k
    if (2 > rtcm->length) {
441
        // ignore zero payload messages, they do not evan have type
442
        // need 2 bytes just to read 10 bit type.
443
367
        GPSD_LOG(LOG_PROG, &context->errout,
444
367
                 "RTCM3: bad payload length %u bitcount %d\n",
445
367
                 rtcm->length, bitcount);
446
367
        return;
447
367
    }
448
1.35k
    rtcm->type = ugrab(12);
449
450
1.35k
    GPSD_LOG(LOG_IO, &context->errout,
451
1.35k
             "RTCM3: type %d payload length %u bitcount %d\n",
452
1.35k
             rtcm->type, rtcm->length, bitcount);
453
454
    // RTCM3 message type numbers start at 1001
455
1.35k
    switch (rtcm->type) {
456
68
    case 1001:
457
68
        msg_name = "GPS Basic RTK, L1 Only";
458
68
        rtcm->rtcmtypes.rtcm3_1001.header.station_id = ugrab(12);
459
68
        rtcm->rtcmtypes.rtcm3_1001.header.tow = ugrab(30);
460
68
        rtcm->rtcmtypes.rtcm3_1001.header.sync = (bool)ugrab(1);
461
68
        n = ugrab(5);
462
68
        if ((8 + (7 * n)) > rtcm->length) {
463
            // not exactly: 8 + (7.25 * n)
464
3
            bad_len = 8 + (7 * n);
465
3
            break;
466
3
        }
467
65
        rtcm->rtcmtypes.rtcm3_1001.header.satcount = n;
468
65
        rtcm->rtcmtypes.rtcm3_1001.header.smoothing = (bool)ugrab(1);
469
65
        rtcm->rtcmtypes.rtcm3_1001.header.interval = ugrab(3);
470
1.12k
#define R1001 rtcm->rtcmtypes.rtcm3_1001.rtk_data[i]
471
441
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1001.header.satcount; i++) {
472
376
            R1001.ident = ugrab(6);
473
376
            R1001.L1.indicator = ugrab(1);
474
376
            GPS_PSEUDORANGE(R1001.L1, 24);
475
376
            RANGEDIFF(R1001.L1, 20);
476
376
            R1001.L1.locktime = (unsigned char)sgrab(7);
477
376
        }
478
65
#undef R1001
479
65
        unknown = false;
480
65
        break;
481
482
76
    case 1002:
483
76
        msg_name = "GPS Extended RTK, L1 Only";
484
76
        rtcm->rtcmtypes.rtcm3_1002.header.station_id = ugrab(12);
485
76
        rtcm->rtcmtypes.rtcm3_1002.header.tow = ugrab(30);
486
76
        rtcm->rtcmtypes.rtcm3_1002.header.sync = (bool)ugrab(1);
487
76
        n = ugrab(5);
488
76
        if ((8 + (9 * n)) > rtcm->length) {
489
            // not exactly: 8 + (9.25 * n)
490
11
            bad_len = 8 + (9 * n);
491
11
            break;
492
11
        }
493
65
        rtcm->rtcmtypes.rtcm3_1002.header.satcount = n;
494
65
        rtcm->rtcmtypes.rtcm3_1002.header.smoothing = (bool)ugrab(1);
495
65
        rtcm->rtcmtypes.rtcm3_1002.header.interval = ugrab(3);
496
1.78k
#define R1002 rtcm->rtcmtypes.rtcm3_1002.rtk_data[i]
497
421
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1002.header.satcount; i++) {
498
356
            R1002.ident = ugrab(6);
499
356
            R1002.L1.indicator = ugrab(1);
500
356
            GPS_PSEUDORANGE(R1002.L1, 24);
501
356
            RANGEDIFF(R1002.L1, 20);
502
356
            R1002.L1.locktime = (unsigned char)sgrab(7);
503
356
            R1002.L1.ambiguity = ugrab(8);
504
356
            R1002.L1.CNR = (ugrab(8)) * CARRIER_NOISE_RATIO_UNITS;
505
356
        }
506
65
#undef R1002
507
65
        unknown = false;
508
65
        break;
509
510
88
    case 1003:
511
88
        msg_name = "GPS Basic RTK, L1 & L2";
512
88
        rtcm->rtcmtypes.rtcm3_1003.header.station_id = ugrab(12);
513
88
        rtcm->rtcmtypes.rtcm3_1003.header.tow = ugrab(30);
514
88
        rtcm->rtcmtypes.rtcm3_1003.header.sync = (bool)ugrab(1);
515
88
        n = ugrab(5);
516
88
        if ((8 + (12 * n)) > rtcm->length) {
517
            // not exactly: 8 + (12.625 * n)
518
5
            bad_len = 8 + (12 * n);
519
5
            break;
520
5
        }
521
83
        rtcm->rtcmtypes.rtcm3_1003.header.satcount = n;
522
83
        rtcm->rtcmtypes.rtcm3_1003.header.smoothing = (bool)ugrab(1);
523
83
        rtcm->rtcmtypes.rtcm3_1003.header.interval = ugrab(3);
524
2.26k
#define R1003 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i]
525
461
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1003.header.satcount; i++) {
526
378
            R1003.ident = ugrab(6);
527
378
            R1003.L1.indicator = ugrab(1);
528
378
            GPS_PSEUDORANGE(R1003.L1, 24);
529
378
            RANGEDIFF(R1003.L1, 20);
530
378
            R1003.L1.locktime = (unsigned char)sgrab(7);
531
378
            R1003.L2.indicator = ugrab(2);
532
378
            GPS_PSEUDORANGE(R1003.L2, 24);
533
378
            temp = (long)sgrab(20);
534
378
            if (temp == GPS_INVALID_PSEUDORANGE) {
535
0
                R1003.L2.rangediff = 0;
536
378
            } else {
537
378
                R1003.L2.rangediff = temp * PSEUDORANGE_DIFF_RESOLUTION;
538
378
            }
539
378
            R1003.L2.locktime = (unsigned char)sgrab(7);
540
378
        }
541
83
#undef R1003
542
83
        unknown = false;
543
83
        break;
544
545
73
    case 1004:
546
73
        msg_name = "GPS Extended RTK, L1 & L2";
547
73
        rtcm->rtcmtypes.rtcm3_1004.header.station_id = ugrab(12);
548
73
        rtcm->rtcmtypes.rtcm3_1004.header.tow = ugrab(30);
549
73
        rtcm->rtcmtypes.rtcm3_1004.header.sync = (bool)ugrab(1);
550
73
        n = ugrab(5);
551
73
        bad_len = ceil(8.0 + (15.625* n));
552
73
        if (bad_len != rtcm->length) {
553
            // exactly: 8 + (15.625 * n)
554
13
            break;
555
13
        }
556
60
        bad_len = 0;
557
60
        rtcm->rtcmtypes.rtcm3_1004.header.satcount = n;
558
60
        rtcm->rtcmtypes.rtcm3_1004.header.smoothing = (bool)ugrab(1);
559
60
        rtcm->rtcmtypes.rtcm3_1004.header.interval = ugrab(3);
560
1.35k
#define R1004 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i]
561
229
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1004.header.satcount; i++) {
562
169
            R1004.ident = ugrab(6);
563
169
            R1004.L1.indicator = (bool)ugrab(1);
564
169
            GPS_PSEUDORANGE(R1004.L1, 24);
565
169
            RANGEDIFF(R1004.L1, 20);
566
169
            R1004.L1.locktime = (unsigned char)sgrab(7);
567
169
            R1004.L1.ambiguity = ugrab(8);
568
169
            R1004.L1.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
569
169
            R1004.L2.indicator = ugrab(2);
570
169
            GPS_PSEUDORANGE(R1004.L2, 14);
571
169
            RANGEDIFF(R1004.L2, 20);
572
169
            R1004.L2.locktime = (unsigned char)sgrab(7);
573
169
            R1004.L2.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
574
169
        }
575
60
#undef R1004
576
60
        unknown = false;
577
60
        break;
578
579
5
    case 1005:
580
5
        msg_name = "Stationary Antenna Reference Point, No Height Information";
581
        // 19 bytes
582
5
        if (19 != rtcm->length) {
583
3
            bad_len = 19;
584
3
            break;
585
3
        }
586
14
#define R1005 rtcm->rtcmtypes.rtcm3_1005
587
2
        R1005.station_id = ugrab(12);
588
2
        ugrab(6);               // reserved
589
2
        R1005.system = ugrab(3);
590
2
        R1005.reference_station = (bool)ugrab(1);
591
2
        R1005.ecef_x = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
592
2
        R1005.single_receiver = ugrab(1);
593
2
        ugrab(1);
594
2
        R1005.ecef_y = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
595
2
        ugrab(2);
596
2
        R1005.ecef_z = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
597
2
#undef R1005
598
2
        unknown = false;
599
2
        break;
600
601
117
    case 1006:
602
117
        msg_name = "Stationary Antenna Reference Point, w/ Height Info";
603
        // 21 bytes
604
117
        if (21 != rtcm->length) {
605
1
            bad_len = 21;
606
1
            break;
607
1
        }
608
928
#define R1006 rtcm->rtcmtypes.rtcm3_1006
609
116
        R1006.station_id = ugrab(12);
610
116
        (void)ugrab(6);         // reserved
611
116
        R1006.system = ugrab(3);
612
116
        R1006.reference_station = (bool)ugrab(1);
613
116
        R1006.ecef_x = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
614
116
        R1006.single_receiver = ugrab(1);
615
116
        ugrab(1);
616
116
        R1006.ecef_y = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
617
116
        ugrab(2);
618
116
        R1006.ecef_z = sgrab(38) * ANTENNA_POSITION_RESOLUTION;
619
116
        R1006.height = ugrab(16) * ANTENNA_POSITION_RESOLUTION;
620
116
#undef R1006
621
116
        unknown = false;
622
116
        break;
623
624
5
    case 1007:
625
5
        msg_name = "Antenna Description";
626
        // 5 to 36 bytes
627
5
        rtcm->rtcmtypes.rtcm3_1007.station_id = ugrab(12);
628
5
        n = ugrab(8);
629
5
        if ((5 + n) != rtcm->length) {
630
3
            bad_len = 5 + n;
631
3
            break;
632
3
        }
633
        // 1007 says DF030 is 20 chars, or less, of ASCII
634
2
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1007.descriptor,
635
2
                                sizeof(rtcm->rtcmtypes.rtcm3_1007.descriptor),
636
2
                                buf + 7, n);
637
2
        bitcount += 8 * n;
638
2
        rtcm->rtcmtypes.rtcm3_1007.setup_id = ugrab(8);
639
2
        unknown = false;
640
2
        break;
641
642
20
    case 1008:
643
20
        msg_name = "Antenna Description & Serial Number";
644
        // 6 to 68 bytes
645
20
        rtcm->rtcmtypes.rtcm3_1008.station_id = ugrab(12);
646
20
        n = ugrab(8);
647
20
        if ((6 + n) > rtcm->length) {
648
5
            bad_len = 6 + n;
649
5
            break;
650
5
        }
651
15
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1008.descriptor,
652
15
                                sizeof(rtcm->rtcmtypes.rtcm3_1008.descriptor),
653
15
                                buf + 7, n);
654
15
        bitcount += 8 * n;
655
15
        rtcm->rtcmtypes.rtcm3_1008.setup_id = ugrab(8);
656
15
        n2 = ugrab(8);
657
15
        if ((6 + n + n2) != rtcm->length) {
658
9
            bad_len = 6 + n + n2;
659
9
            break;
660
9
        }
661
6
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1008.serial,
662
6
                                sizeof(rtcm->rtcmtypes.rtcm3_1008.serial),
663
6
                                buf + 9 + n, n2);
664
        // bitcount += 8 * n2;
665
6
        unknown = false;
666
6
        break;
667
668
59
    case 1009:
669
59
        msg_name = "GLONASS Basic RTK, L1 Only";
670
59
        rtcm->rtcmtypes.rtcm3_1009.header.station_id = ugrab(12);
671
59
        rtcm->rtcmtypes.rtcm3_1009.header.tow = ugrab(27);
672
59
        rtcm->rtcmtypes.rtcm3_1009.header.sync = (bool)ugrab(1);
673
59
        n = ugrab(5);
674
59
        if ((7 + (8 * n)) > rtcm->length) {
675
            // not exactly: 7.625 + (8 * n)
676
8
            bad_len = 7 + (8 * n);
677
8
            break;
678
8
        }
679
51
        rtcm->rtcmtypes.rtcm3_1009.header.satcount = n;
680
51
        rtcm->rtcmtypes.rtcm3_1009.header.smoothing = (bool)ugrab(1);
681
51
        rtcm->rtcmtypes.rtcm3_1009.header.interval = ugrab(3);
682
1.00k
#define R1009 rtcm->rtcmtypes.rtcm3_1009.rtk_data[i]
683
252
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1009.header.satcount; i++) {
684
201
            R1009.ident = ugrab(6);
685
201
            R1009.L1.indicator = (bool)ugrab(1);
686
201
            R1009.L1.channel = (short)ugrab(5) - GLONASS_CHANNEL_BASE;
687
201
            R1009.L1.pseudorange = ugrab(25) * GLONASS_PSEUDORANGE_RESOLUTION;
688
201
            RANGEDIFF(R1009.L1, 20);
689
201
            R1009.L1.locktime = (unsigned char)sgrab(7);
690
201
        }
691
51
#undef R1009
692
51
        unknown = false;
693
51
        break;
694
695
57
    case 1010:
696
57
        msg_name = "GLONASS Extended RTK, L1 Only";
697
57
        rtcm->rtcmtypes.rtcm3_1010.header.station_id =
698
57
            (unsigned short)ugrab(12);
699
57
        rtcm->rtcmtypes.rtcm3_1010.header.tow = ugrab(27);
700
57
        rtcm->rtcmtypes.rtcm3_1010.header.sync = (bool)ugrab(1);
701
57
        n = ugrab(5);
702
57
        bad_len = ceil(7.625 + (9.875 * n));
703
57
        if (bad_len != rtcm->length) {
704
            // exactly: 7.625 + (9.875 * n)
705
15
            break;
706
15
        }
707
42
        bad_len = 0;
708
42
        rtcm->rtcmtypes.rtcm3_1010.header.satcount = n;
709
42
        rtcm->rtcmtypes.rtcm3_1010.header.smoothing = (bool)ugrab(1);
710
42
        rtcm->rtcmtypes.rtcm3_1010.header.interval = ugrab(3);
711
924
#define R1010 rtcm->rtcmtypes.rtcm3_1010.rtk_data[i]
712
174
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1010.header.satcount; i++) {
713
132
            R1010.ident = (unsigned short)ugrab(6);
714
132
            R1010.L1.indicator = (bool)ugrab(1);
715
132
            R1010.L1.channel = (short)ugrab(5) - GLONASS_CHANNEL_BASE;
716
132
            R1010.L1.pseudorange = ugrab(25) * GLONASS_PSEUDORANGE_RESOLUTION;
717
132
            RANGEDIFF(R1010.L1, 20);
718
132
            R1010.L1.locktime = (unsigned char)sgrab(7);
719
132
            R1010.L1.ambiguity = (unsigned char)ugrab(7);
720
132
            R1010.L1.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
721
132
        }
722
42
#undef R1010
723
42
        unknown = false;
724
42
        break;
725
726
65
    case 1011:
727
65
        msg_name = "GLONASS Basic RTK, L1 & L2";
728
65
        rtcm->rtcmtypes.rtcm3_1011.header.station_id =
729
65
            (unsigned short)ugrab(12);
730
65
        rtcm->rtcmtypes.rtcm3_1011.header.tow = ugrab(27);
731
65
        rtcm->rtcmtypes.rtcm3_1011.header.sync = (bool)ugrab(1);
732
65
        n = ugrab(5);
733
65
        bad_len = ceil(7.625 + (13.325 * n));
734
65
        if (bad_len != rtcm->length) {
735
            // exactly: 7.625 + (13.325 * n)
736
11
            break;
737
11
        }
738
54
        bad_len = 0;
739
54
        rtcm->rtcmtypes.rtcm3_1011.header.satcount = n;
740
54
        rtcm->rtcmtypes.rtcm3_1011.header.smoothing = (bool)ugrab(1);
741
54
        rtcm->rtcmtypes.rtcm3_1011.header.interval = ugrab(3);
742
2.53k
#define R1011 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i]
743
249
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1011.header.satcount; i++) {
744
195
            R1011.ident = (unsigned short)ugrab(6);
745
195
            R1011.L1.indicator = (bool)ugrab(1);
746
195
            R1011.L1.channel = (short)ugrab(5) - GLONASS_CHANNEL_BASE;
747
195
            R1011.L1.pseudorange = ugrab(25) * GLONASS_PSEUDORANGE_RESOLUTION;
748
195
            RANGEDIFF(R1011.L1, 20);
749
195
            R1011.L1.locktime = (unsigned char)sgrab(7);
750
195
            R1011.L1.ambiguity = (unsigned char)ugrab(7);
751
195
            R1011.L1.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
752
195
            R1011.L2.indicator = (bool)ugrab(1);
753
195
            R1011.L2.channel = (short)ugrab(5) - GLONASS_CHANNEL_BASE;
754
195
            R1011.L2.pseudorange = ugrab(25) * GLONASS_PSEUDORANGE_RESOLUTION;
755
195
            RANGEDIFF(R1011.L2, 20);
756
195
            R1011.L2.locktime = (unsigned char)sgrab(7);
757
195
            R1011.L2.ambiguity = (unsigned char)ugrab(7);
758
195
            R1011.L2.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
759
195
        }
760
54
#undef R1011
761
54
        unknown = false;
762
54
        break;
763
764
78
    case 1012:
765
78
        msg_name = "GLONASS Extended RTK, L1 & L2";
766
78
        rtcm->rtcmtypes.rtcm3_1012.header.station_id = ugrab(12);
767
78
        rtcm->rtcmtypes.rtcm3_1012.header.tow = ugrab(27);
768
78
        rtcm->rtcmtypes.rtcm3_1012.header.sync = (bool)ugrab(1);
769
78
        n = ugrab(5);
770
78
        bad_len = ceil(7.625 + (16.25 * n));
771
78
        if (bad_len != rtcm->length) {
772
            // exactly: 7.625 + (16.25 * n)
773
11
            break;
774
11
        }
775
67
        bad_len = 0;
776
67
        rtcm->rtcmtypes.rtcm3_1012.header.satcount = n;
777
67
        rtcm->rtcmtypes.rtcm3_1012.header.smoothing = (bool)ugrab(1);
778
67
        rtcm->rtcmtypes.rtcm3_1012.header.interval = ugrab(3);
779
1.78k
#define R1012 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i]
780
229
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1012.header.satcount; i++) {
781
162
            unsigned rangeincr;
782
783
162
            R1012.ident = ugrab(6);
784
162
            R1012.L1.indicator = (bool)ugrab(1);
785
162
            R1012.L1.channel = (short)ugrab(5) - GLONASS_CHANNEL_BASE;
786
162
            R1012.L1.pseudorange = ugrab(25) * GLONASS_PSEUDORANGE_RESOLUTION;
787
162
            RANGEDIFF(R1012.L1, 20);
788
162
            R1012.L1.locktime = ugrab(7);
789
162
            R1012.L1.ambiguity = ugrab(7);
790
162
            R1012.L1.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
791
162
            R1012.L2.indicator = (bool)ugrab(2);
792
162
            rangeincr = ugrab(14);
793
162
            if (rangeincr == GLONASS_INVALID_RANGEINCR) {
794
10
                R1012.L2.pseudorange = 0;
795
152
            } else {
796
152
                R1012.L2.pseudorange = (rangeincr *
797
152
                                        GLONASS_PSEUDORANGE_RESOLUTION);
798
152
            }
799
162
            RANGEDIFF(R1012.L2, 20);
800
162
            R1012.L2.locktime = (unsigned char)sgrab(7);
801
162
            R1012.L2.CNR = ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
802
162
        }
803
67
#undef R1012
804
67
        unknown = false;
805
67
        break;
806
807
12
    case 1013:
808
12
        msg_name = "System Parameters";
809
12
        rtcm->rtcmtypes.rtcm3_1013.station_id = ugrab(12);
810
12
        rtcm->rtcmtypes.rtcm3_1013.mjd = ugrab(16);
811
12
        rtcm->rtcmtypes.rtcm3_1013.sod = ugrab(17);
812
12
        n = ugrab(5);
813
12
        bad_len = ceil(8.75 + (3.625 * n));
814
12
        if (bad_len != rtcm->length) {
815
            // exactly: 8.75 + (3.625 * n)
816
3
            break;
817
3
        }
818
9
        bad_len = 0;
819
9
        rtcm->rtcmtypes.rtcm3_1013.ncount = n;
820
9
        rtcm->rtcmtypes.rtcm3_1013.leapsecs = ugrab(8);
821
159
#define R1013 rtcm->rtcmtypes.rtcm3_1013.announcements[i]
822
62
        for (i = 0; i < rtcm->rtcmtypes.rtcm3_1013.ncount; i++) {
823
53
            R1013.id = ugrab(12);
824
53
            R1013.sync = (bool)ugrab(1);
825
53
            R1013.interval = ugrab(16);
826
53
        }
827
9
#undef R1013
828
9
        unknown = false;
829
9
        break;
830
831
3
    case 1014:
832
3
        msg_name = "Network Auxiliary Station Data";
833
        // coordinate difference between one Aux station and master station
834
3
        if (15 != rtcm->length) {
835
2
            bad_len = 15;
836
2
            break;
837
2
        }
838
1
        rtcm->rtcmtypes.rtcm3_1014.network_id = (int)ugrab(8);
839
1
        rtcm->rtcmtypes.rtcm3_1014.subnetwork_id = (int)ugrab(4);
840
1
        rtcm->rtcmtypes.rtcm3_1014.stationcount = (char)ugrab(5);
841
1
        rtcm->rtcmtypes.rtcm3_1014.master_id = (int)ugrab(12);
842
1
        rtcm->rtcmtypes.rtcm3_1014.aux_id = (int)ugrab(12);
843
1
        rtcm->rtcmtypes.rtcm3_1014.d_lat =
844
1
            ugrab(20) * ANTENNA_DEGREE_RESOLUTION;
845
1
        rtcm->rtcmtypes.rtcm3_1014.d_lon =
846
1
            ugrab(21) * ANTENNA_DEGREE_RESOLUTION;
847
1
        rtcm->rtcmtypes.rtcm3_1014.d_alt = ugrab(23) / 1000;
848
1
        unknown = false;
849
1
        break;
850
851
8
    case 1015:
852
        /* RTCM 3.1
853
         * GPS Ionospheric Correction Differences for all satellites
854
         * between the master station and one auxiliary station
855
         * 9 bytes minimum
856
         */
857
8
        if (9 > rtcm->length) {
858
            // need 76 bits, 9.5 bytes
859
3
            bad_len = 9;
860
3
            break;
861
3
        }
862
863
5
        unknown = rtcm3_101567(context, rtcm, buf);
864
5
        msg_name = "GPS Ionospheric Correction Differences";
865
5
        break;
866
867
3
    case 1016:
868
        /* RTCM 3.1
869
         * GPS Geometric Correction Differences for all satellites between
870
         * the master station and one auxiliary station.
871
         * 9 bytes minimum
872
         */
873
3
        if (9 > rtcm->length) {
874
            // need 76 bits, 9.5 bytes
875
1
            bad_len = 9;
876
1
            break;
877
1
        }
878
2
        unknown = rtcm3_101567(context, rtcm, buf);
879
2
        msg_name = "GPS Geometric Correction Differences";
880
2
        break;
881
882
8
    case 1017:
883
        /* RTCM 3.1
884
         * GPS Combined Geometric and Ionospheric Correction Differences
885
         * for all satellites between one Aux station and the master station
886
         * (same content as both types 1015 and 1016 together, but less size)
887
         * 9 bytes minimum
888
         */
889
8
        if (9 > rtcm->length) {
890
            // need 76 bits, 9.5 bytes
891
2
            bad_len = 9;
892
2
            break;
893
2
        }
894
6
        unknown = rtcm3_101567(context, rtcm, buf);
895
6
        unknown = rtcm3_101567(context, rtcm, buf);
896
6
        msg_name = "GPS Combined Geometric and Ionospheric "
897
6
                       "Correction Differences";
898
6
        break;
899
900
1
    case 1018:
901
        /* RTCM 3.1
902
         * Reserved for alternative Ionospheric Correction Difference Message
903
         */
904
1
        msg_name = "Reserved for alternative Ionospheric Correction "
905
1
                       "Differences";
906
1
        break;
907
908
3
    case 1019:
909
        /* RTCM 3.1 - 1020
910
         * GPS Ephemeris
911
         * 62 bytes
912
         */
913
3
        if (61 != rtcm->length) {
914
2
            bad_len = 61;
915
2
            break;
916
2
        }
917
        // TODO: rtklib has C code for this one.
918
1
        msg_name = "GPS Ephemeris";
919
1
        break;
920
921
10
    case 1020:
922
        /* RTCM 3.1 - 1020
923
         * GLONASS Ephemeris
924
         * 45 bytes
925
         */
926
10
        if (45 != rtcm->length) {
927
9
            bad_len = 45;
928
9
            break;
929
9
        }
930
        // TODO: rtklib has C code for this one.
931
1
        msg_name = "GLO Ephemeris";
932
1
        break;
933
934
16
    case 1021:
935
        /* RTCM 3.1
936
         * Helmert / Abridged Molodenski Transformation parameters
937
         */
938
16
        msg_name = "Helmert / Abridged Molodenski Transformation "
939
16
                       "parameters";
940
16
        if (51 > rtcm->length) {
941
            // actually 51.5 + n + m
942
3
            bad_len = 51;
943
3
            break;
944
3
        }
945
        // Set Source-Name
946
13
        n = ugrab(5);
947
13
        if ((sizeof(rtcm->rtcmtypes.rtcm3_1021.src_name) - 1) <= n) {
948
            // paranoia
949
1
            n = sizeof(rtcm->rtcmtypes.rtcm3_1021.src_name) - 1;
950
1
        }
951
187
        for (i = 0; i < n; i++) {
952
            // Grrr.  Not byte aligned
953
174
            rtcm->rtcmtypes.rtcm3_1021.src_name[i] = (char)ugrab(8);
954
174
        }
955
13
        rtcm->rtcmtypes.rtcm3_1021.src_name[n] = '\0';
956
        // Set Target-Name
957
13
        n2 = (unsigned)ugrab(5);
958
13
        if ((sizeof(rtcm->rtcmtypes.rtcm3_1021.tar_name) - 1) <= n2) {
959
            // paranoia
960
1
            n2 = sizeof(rtcm->rtcmtypes.rtcm3_1021.tar_name) - 1;
961
1
        }
962
178
        for (i = 0; i < n2; i++) {
963
165
            rtcm->rtcmtypes.rtcm3_1021.tar_name[i] = (char)ugrab(8);
964
165
        }
965
13
        rtcm->rtcmtypes.rtcm3_1021.tar_name[n2] = '\0';
966
13
        rtcm->rtcmtypes.rtcm3_1021.sys_id_num = ugrab(8);
967
130
#define R1021 rtcm->rtcmtypes.rtcm3_1021.ut_tr_msg_id[i]
968
143
        for (i = 0; i < RTCM3_DF148_SIZE; i++) {
969
130
            R1021 = (bool)ugrab(1);
970
130
        }
971
13
#undef R1021
972
13
        rtcm->rtcmtypes.rtcm3_1021.plate_number = ugrab(5);
973
13
        rtcm->rtcmtypes.rtcm3_1021.computation_id = ugrab(4);
974
13
        rtcm->rtcmtypes.rtcm3_1021.height_id = ugrab(2);
975
13
        rtcm->rtcmtypes.rtcm3_1021.lat_origin = sgrab(19) *
976
13
            VALIDITY_RESOLUTION / DEG_ARCSEC_RESOLUTION;
977
13
        rtcm->rtcmtypes.rtcm3_1021.lon_origin = sgrab(20) *
978
13
            VALIDITY_RESOLUTION / DEG_ARCSEC_RESOLUTION;
979
13
        rtcm->rtcmtypes.rtcm3_1021.lat_extension = sgrab(14) *
980
13
            VALIDITY_RESOLUTION / DEG_ARCSEC_RESOLUTION;
981
13
        rtcm->rtcmtypes.rtcm3_1021.lon_extension = sgrab(14) *
982
13
            VALIDITY_RESOLUTION / DEG_ARCSEC_RESOLUTION;
983
13
        rtcm->rtcmtypes.rtcm3_1021.x_trans = sgrab(23) *
984
13
            TRANSLATION_MM_RESOLUTION;
985
13
        rtcm->rtcmtypes.rtcm3_1021.y_trans = sgrab(23) *
986
13
            TRANSLATION_MM_RESOLUTION;
987
13
        rtcm->rtcmtypes.rtcm3_1021.z_trans = sgrab(23) *
988
13
            TRANSLATION_MM_RESOLUTION;
989
13
        rtcm->rtcmtypes.rtcm3_1021.x_rot = sgrab(32) *
990
13
            ROTATION_ARCSEC_RESOLUTION / DEG_ARCSEC_RESOLUTION;
991
13
        rtcm->rtcmtypes.rtcm3_1021.y_rot = sgrab(32) *
992
13
            ROTATION_ARCSEC_RESOLUTION / DEG_ARCSEC_RESOLUTION;
993
13
        rtcm->rtcmtypes.rtcm3_1021.z_rot = sgrab(32) *
994
13
            ROTATION_ARCSEC_RESOLUTION / DEG_ARCSEC_RESOLUTION;
995
13
        rtcm->rtcmtypes.rtcm3_1021.ds = sgrab(25) * SCALE_PPM_RESOLUTION;
996
13
        rtcm->rtcmtypes.rtcm3_1021.add_as = sgrab(24) *
997
13
            TRANSLATION_MM_RESOLUTION;
998
13
        rtcm->rtcmtypes.rtcm3_1021.add_bs = sgrab(25) *
999
13
            TRANSLATION_MM_RESOLUTION;
1000
13
        rtcm->rtcmtypes.rtcm3_1021.add_at = sgrab(24) *
1001
13
            TRANSLATION_MM_RESOLUTION;
1002
13
        rtcm->rtcmtypes.rtcm3_1021.add_bt = sgrab(25) *
1003
13
            TRANSLATION_MM_RESOLUTION;
1004
13
        rtcm->rtcmtypes.rtcm3_1021.quality_hori = ugrab(3);
1005
13
        rtcm->rtcmtypes.rtcm3_1021.quality_vert = ugrab(3);
1006
1007
13
        unknown = false;
1008
13
        break;
1009
1010
11
    case 1022:
1011
        /* RTCM 3.1
1012
         * Molodenski-Badekas transformation parameters
1013
         */
1014
11
        msg_name = "Molodenski-Badekas transformation parameters";
1015
11
        if (64 > rtcm->length) {
1016
            // actually 64,625 + n + m
1017
7
            bad_len = 64;
1018
7
            break;
1019
7
        }
1020
4
        break;
1021
1022
9
    case 1023:
1023
        /* RTCM 3.1
1024
         * Residuals Ellipsoidal Grid Representation
1025
         */
1026
9
        msg_name = "Residuals Ellipsoidal Grid Representation";
1027
9
        if (72 > rtcm->length) {
1028
            // actually 72,25
1029
3
            bad_len = 72;
1030
3
            break;
1031
3
        }
1032
6
        rtcm->rtcmtypes.rtcm3_1023.sys_id_num = ugrab(8);
1033
6
        rtcm->rtcmtypes.rtcm3_1023.shift_id_hori = (bool)ugrab(1);
1034
6
        rtcm->rtcmtypes.rtcm3_1023.shift_id_vert = (bool)ugrab(1);
1035
6
        rtcm->rtcmtypes.rtcm3_1023.lat_origin = sgrab(21) *
1036
6
            PHASE_CORRECTION_RESOLUTION / DEG_ARCSEC_RESOLUTION;
1037
6
        rtcm->rtcmtypes.rtcm3_1023.lon_origin = sgrab(22) *
1038
6
            PHASE_CORRECTION_RESOLUTION / DEG_ARCSEC_RESOLUTION;
1039
6
        rtcm->rtcmtypes.rtcm3_1023.lat_extension = ugrab(12) *
1040
6
            PHASE_CORRECTION_RESOLUTION / DEG_ARCSEC_RESOLUTION;
1041
6
        rtcm->rtcmtypes.rtcm3_1023.lon_extension = ugrab(12) *
1042
6
            PHASE_CORRECTION_RESOLUTION / DEG_ARCSEC_RESOLUTION;
1043
6
        rtcm->rtcmtypes.rtcm3_1023.lat_mean = sgrab(8) *
1044
6
            TRANSLATION_MM_RESOLUTION;
1045
6
        rtcm->rtcmtypes.rtcm3_1023.lon_mean = sgrab(8) *
1046
6
            TRANSLATION_MM_RESOLUTION;
1047
6
        rtcm->rtcmtypes.rtcm3_1023.hgt_mean = sgrab(15) * CM_RESOLUTION;
1048
288
#define R1023 rtcm->rtcmtypes.rtcm3_1023.residuals[i]
1049
102
        for (i = 0; i < RTCM3_GRID_SIZE; i++) {
1050
96
            R1023.lat_res = sgrab(9) * RES_ARCSEC_RESOLUTION;
1051
96
            R1023.lon_res = sgrab(9) * RES_ARCSEC_RESOLUTION;
1052
96
            R1023.hgt_res = sgrab(9) * TRANSLATION_MM_RESOLUTION;
1053
96
        }
1054
6
#undef R1023
1055
6
        rtcm->rtcmtypes.rtcm3_1023.interp_meth_id_hori = ugrab(2);
1056
6
        rtcm->rtcmtypes.rtcm3_1023.interp_meth_id_vert = ugrab(2);
1057
6
        rtcm->rtcmtypes.rtcm3_1023.grd_qual_id_hori = ugrab(3);
1058
6
        rtcm->rtcmtypes.rtcm3_1023.grd_qual_id_vert = ugrab(3);
1059
6
        rtcm->rtcmtypes.rtcm3_1023.mjd = ugrab(16);
1060
6
        unknown = false;
1061
6
        break;
1062
1063
2
    case 1024:
1064
        /* RTCM 3.1
1065
         * Residuals Plane Grid Representation
1066
         */
1067
2
        msg_name = "Residuals Plane Grid Representation";
1068
2
        if (72 > rtcm->length) {
1069
            // actually 72,75
1070
1
            bad_len = 72;
1071
1
            break;
1072
1
        }
1073
1
        break;
1074
1075
9
    case 1025:
1076
        /* RTCM 3.1
1077
         * Projection Parameters, Projection Types other than LCC2SP
1078
         */
1079
9
        msg_name = "Projection Parameters, Projection Types other "
1080
9
                       "than LCC2SP";
1081
9
        if (24 > rtcm->length) {
1082
            // actually 24.5
1083
5
            bad_len = 24;
1084
5
            break;
1085
5
        }
1086
4
        rtcm->rtcmtypes.rtcm3_1025.sys_id_num = ugrab(8);
1087
4
        rtcm->rtcmtypes.rtcm3_1025.projection_type = ugrab(6);
1088
4
        rtcm->rtcmtypes.rtcm3_1025.lat_origin = sgrab(34) *
1089
4
            PROJ_ORIGIN_RESOLUTION;
1090
4
        rtcm->rtcmtypes.rtcm3_1025.lon_origin = sgrab(35) *
1091
4
            PROJ_ORIGIN_RESOLUTION;
1092
4
        rtcm->rtcmtypes.rtcm3_1025.add_sno = ugrab(30) *
1093
4
            SCALE_PPM_RESOLUTION;
1094
4
        rtcm->rtcmtypes.rtcm3_1025.false_east = ugrab(36) *
1095
4
            TRANSLATION_MM_RESOLUTION;
1096
4
        rtcm->rtcmtypes.rtcm3_1025.false_north = ugrab(35) *
1097
4
            TRANSLATION_MM_RESOLUTION;
1098
4
        unknown = false;
1099
4
        break;
1100
1101
5
    case 1026:
1102
        /* RTCM 3.1
1103
         * Projection Parameters, Projection Type LCC2SP
1104
         * (Lambert Conic Conformal)
1105
         */
1106
5
        msg_name = "Projection Parameters, Projection Type LCC2SP";
1107
5
        if (29 > rtcm->length) {
1108
            // actually 29.25
1109
3
            bad_len = 29;
1110
3
            break;
1111
3
        }
1112
2
        break;
1113
1114
3
    case 1027:
1115
        /* RTCM 3.1
1116
         * Projection Parameters, Projection Type OM (Oblique Mercator)
1117
         */
1118
3
        msg_name = "Projection Parameters, Projection Type OM";
1119
3
        if (32 > rtcm->length) {
1120
            // actually 32.25
1121
1
            bad_len = 32;
1122
1
            break;
1123
1
        }
1124
2
        break;
1125
1126
2
    case 1028:
1127
        /* RTCM 3.1
1128
         * Reserved for global to plate fixed transformation
1129
         */
1130
1
        msg_name = "Reserved, Global to Plate Transformation";
1131
1
        break;
1132
1133
12
    case 1029:
1134
12
        msg_name = "Text in UTF8 format";
1135
        /* 9 bytes minimum
1136
         * (max. 127 multibyte characters and max. 255 bytes)
1137
         */
1138
12
        rtcm->rtcmtypes.rtcm3_1029.station_id = ugrab(12);
1139
12
        rtcm->rtcmtypes.rtcm3_1029.mjd = ugrab(16);
1140
12
        rtcm->rtcmtypes.rtcm3_1029.sod = ugrab(17);
1141
12
        rtcm->rtcmtypes.rtcm3_1029.len = ugrab(7);
1142
12
        n = ugrab(8);
1143
12
        if ((9 + n) != rtcm->length) {
1144
11
            bad_len = 9 + n;
1145
11
            break;
1146
11
        }
1147
1
        rtcm->rtcmtypes.rtcm3_1029.unicode_units = n;
1148
1
        rtcm3_copy_string_field((char *)rtcm->rtcmtypes.rtcm3_1029.text,
1149
1
                                sizeof(rtcm->rtcmtypes.rtcm3_1029.text),
1150
1
                                buf + 12,
1151
1
                                rtcm->rtcmtypes.rtcm3_1029.unicode_units);
1152
1
        unknown = false;
1153
1
        break;
1154
1155
3
    case 1030:
1156
        /* RTCM 3.1
1157
         * GPS Network RTK Residual Message
1158
         */
1159
3
        msg_name = "GPS Network RTK Residual";
1160
3
        if (7 > rtcm->length) {
1161
            // actually 7 + (6.125 * n)
1162
2
            bad_len = 7;
1163
2
            break;
1164
2
        }
1165
1
        break;
1166
1167
4
    case 1031:
1168
        /* RTCM 3.1
1169
         * GLONASS Network RTK Residual Message
1170
         */
1171
4
        msg_name = "GLONASS Network RTK Residual";
1172
4
        if (6 > rtcm->length) {
1173
            // actually 6.625 + (6.125 ( n)
1174
2
            bad_len = 6;
1175
2
            break;
1176
2
        }
1177
2
        break;
1178
1179
9
    case 1032:
1180
        /* RTCM 3.1
1181
         * Physical Reference Station Position message
1182
         */
1183
9
        msg_name = "Physical Reference Station Position";
1184
9
        if (19 > rtcm->length) {
1185
            // actually 19.5
1186
6
            bad_len = 19;
1187
6
            break;
1188
6
        }
1189
3
        break;
1190
1191
29
    case 1033:                  // see note in header
1192
29
        msg_name ="Receiver and Antenna Descriptor";
1193
        /* Type1033 is a combined Message Types 1007 and 1008
1194
         * and hence contains antenna descriptor and serial number
1195
         * as well as receiver descriptor and serial number.
1196
         */
1197
        // TODO: rtklib has C code for this one.
1198
29
        rtcm->rtcmtypes.rtcm3_1033.station_id = ugrab(12);
1199
29
        n = ugrab(8);
1200
29
        if ((28 + n) > rtcm->length) {
1201
8
            bad_len = 28 + n;
1202
8
            break;
1203
8
        }
1204
21
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1033.descriptor,
1205
21
                                sizeof(rtcm->rtcmtypes.rtcm3_1033.descriptor),
1206
21
                                buf + 7, n);
1207
21
        bitcount += 8 * n;
1208
21
        rtcm->rtcmtypes.rtcm3_1033.setup_id = ugrab(8);
1209
21
        n2 = ugrab(8);
1210
1211
21
        if ((8 + n + n2) > rtcm->length) {
1212
6
            bad_len = 8 + n + n2;
1213
6
            break;
1214
6
        }
1215
15
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1033.serial,
1216
15
                                sizeof(rtcm->rtcmtypes.rtcm3_1033.serial),
1217
15
                                buf + 9 + n, n2);
1218
15
        bitcount += 8 * n2;
1219
15
        n3 = ugrab(8);
1220
15
        if ((8 + n + n2 + n3) > rtcm->length) {
1221
5
            bad_len = 9 + n + n2 + n3;
1222
5
            break;
1223
5
        }
1224
10
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1033.receiver,
1225
10
                                sizeof(rtcm->rtcmtypes.rtcm3_1033.receiver),
1226
10
                                buf + 10 + n + n2, n3);
1227
10
        bitcount += 8 * n3;
1228
10
        n4 = ugrab(8);
1229
1230
10
        if ((9 + n + n2 + n3 + n4) > rtcm->length) {
1231
6
            bad_len = 9 + n + n2 + n3 + n4;
1232
6
            break;
1233
6
        }
1234
4
        rtcm3_copy_string_field(rtcm->rtcmtypes.rtcm3_1033.firmware,
1235
4
                                sizeof(rtcm->rtcmtypes.rtcm3_1033.firmware),
1236
4
                                buf + 11 + n + n2 + n3, n4);
1237
        // bitcount += 8 * n4;
1238
        // TODO: next is receiver serial number
1239
4
        unknown = false;
1240
4
        break;
1241
1242
5
    case 1034:
1243
        /* RTCM 3.2
1244
         * GPS Network FKP Gradient Message
1245
         */
1246
5
        msg_name = "GPS Network FKP Gradient";
1247
5
        if (6 > rtcm->length) {
1248
            // not exactly: 6.125 + (8.25 * n)
1249
2
            bad_len = 6;
1250
2
            break;
1251
2
        }
1252
3
        break;
1253
1254
3
    case 1035:
1255
        /* RTCM 3.2
1256
         * GLONASS Network FKP Gradient Message
1257
         */
1258
3
        msg_name = "GLO Network FKP Gradient";
1259
3
        if (5 > rtcm->length) {
1260
            // not exactly: 5.75 + (8.25 * n)
1261
1
            bad_len = 5;
1262
1
            break;
1263
1
        }
1264
2
        break;
1265
1266
6
    case 1037:
1267
        /* RTCM 3.2
1268
         * GLONASS Ionospheric Correction Differences
1269
         */
1270
6
        msg_name = "GLO Ionospheric Correction Differences";
1271
6
        if (9 > rtcm->length) {
1272
            // not exactly: 9.125 + (3,5 * n)
1273
1
            bad_len = 9;
1274
1
            break;
1275
1
        }
1276
5
        break;
1277
1278
5
    case 1038:
1279
        /* RTCM 3.2
1280
         * GLONASS Geometric Correction Differences
1281
         */
1282
2
        msg_name = "GLO Geometric Correction Differences";
1283
2
        if (9 > rtcm->length) {
1284
            // not exactly: 9.125 + (4,5 * n)
1285
1
            bad_len = 9;
1286
1
            break;
1287
1
        }
1288
1
        break;
1289
1290
2
    case 1039:
1291
        /* RTCM 3.2
1292
         * GLONASS Combined Geometric and Ionospheric Correction Differences
1293
         */
1294
2
        msg_name = "GLONASS Combined Geometric and Ionospheric "
1295
2
                   "Correction Differences";
1296
2
        if (9 > rtcm->length) {
1297
            // not exactly: 9.125 + (6.625 * n)
1298
1
            bad_len = 9;
1299
1
            break;
1300
1
        }
1301
1
        break;
1302
1303
9
    case 1042:
1304
        /* RTCM 3.x - 1043
1305
         * BeiDou Ephemeris
1306
         * length 64
1307
         */
1308
9
        msg_name = "BD Ephemeris";
1309
9
        if (64 != rtcm->length) {
1310
8
            bad_len = 64;
1311
8
            break;
1312
8
        }
1313
1
        break;
1314
1315
5
    case 1043:
1316
        /* RTCM 3.x - 1043
1317
         * SBAS Ephemeris
1318
         * length 29
1319
         */
1320
5
        msg_name = "SBAS Ephemeris";
1321
5
        if (29 != rtcm->length) {
1322
4
            bad_len = 29;
1323
4
            break;
1324
4
        }
1325
1
        break;
1326
1327
12
    case 1044:
1328
        /* RTCM 3.x - 1044
1329
         * QZSS ephemeris
1330
         * length 61
1331
         */
1332
        // TODO: rtklib has C code for this one.
1333
12
        msg_name = "QZSS Ephemeris";
1334
12
        if (61 != rtcm->length) {
1335
11
            bad_len = 61;
1336
11
            break;
1337
11
        }
1338
1
        break;
1339
1340
3
    case 1045:
1341
        /* RTCM 3.2 - 1045
1342
         * Galileo F/NAV Ephemeris Data
1343
         * 62 bytes
1344
         */
1345
        // TODO: rtklib has C code for this one.
1346
3
        msg_name = "GAL F/NAV Ephemeris Data";
1347
3
        if (62 != rtcm->length) {
1348
2
            bad_len = 62;
1349
2
            break;
1350
2
        }
1351
1
        break;
1352
1353
4
    case 1046:
1354
        /* RTCM 3.x - 1046
1355
         * Galileo I/NAV Ephemeris Data
1356
         * length 63
1357
         */
1358
        // TODO: rtklib has C code for this one.
1359
4
        msg_name = "GAL I/NAV Ephemeris Data";
1360
4
        if (63 != rtcm->length) {
1361
3
            bad_len = 63;
1362
3
            break;
1363
3
        }
1364
1
        break;
1365
1366
4
    case 1057:
1367
        /* RTCM 3.2
1368
         * SSR GPS Orbit Correction
1369
         */
1370
4
        msg_name = "SSR GPS Orbit Correction";
1371
4
        if (8 > rtcm->length) {
1372
            // not exactly: 8.5 + (6.875 * n)
1373
2
            bad_len = 8;
1374
2
            break;
1375
2
        }
1376
2
        break;
1377
1378
3
    case 1058:
1379
        /* RTCM 3.2
1380
         * SSR GPS Clock Correction
1381
         */
1382
3
        msg_name = "SSR GPS Clock Correction";
1383
3
        if (8 > rtcm->length) {
1384
            // not exactly: 8.375 + (9.5 * n)
1385
1
            bad_len = 8;
1386
1
            break;
1387
1
        }
1388
2
        break;
1389
1390
3
    case 1059:
1391
        /* RTCM 3.2
1392
         * SSR GPS Code Bias
1393
         */
1394
3
        msg_name = "SSR GPS Code Bias";
1395
3
        if (8 > rtcm->length) {
1396
            // not exactly: 8.375 + (1.375 * n) + (2.375 * ??)
1397
2
            bad_len = 8;
1398
2
            break;
1399
2
        }
1400
1
        break;
1401
1402
5
    case 1060:
1403
        /* RTCM 3.2
1404
         * SSR GPS Combined Orbit and Clock Correction
1405
         */
1406
5
        msg_name = "SSR GPS Combined Orbit and Clock Correction";
1407
5
        if (8 > rtcm->length) {
1408
            // not exactly: 8.5 + (25.625 * n)
1409
3
            bad_len = 8;
1410
3
            break;
1411
3
        }
1412
2
        break;
1413
1414
3
    case 1061:
1415
        /* RTCM 3.2
1416
         * SSR GPS URA
1417
         */
1418
3
        msg_name = "SSR GPS URA";
1419
3
        if (8 > rtcm->length) {
1420
            // not exactly: 8.375 + (1.5 * n)
1421
1
            bad_len = 8;
1422
1
            break;
1423
1
        }
1424
2
        break;
1425
1426
6
    case 1062:
1427
        /* RTCM 3.2
1428
         * SSR GPS High Rate Clock Correction
1429
         */
1430
6
        msg_name = "SSR GPS High Rate Clock Correction";
1431
6
        if (8 > rtcm->length) {
1432
            // not exactly: 8.375 + (3.5 * n)
1433
2
            bad_len = 8;
1434
2
            break;
1435
2
        }
1436
4
        break;
1437
1438
5
    case 1063:
1439
        /* RTCM 3.2
1440
         * SSR GLO Orbit Correction
1441
         */
1442
5
        msg_name = "SSR GLO Orbit Correction";
1443
5
        if (8 > rtcm->length) {
1444
            // not exactly: 8.125 + (16.75 * n)
1445
4
            bad_len = 8;
1446
4
            break;
1447
4
        }
1448
1
        break;
1449
1450
4
    case 1064:
1451
        /* RTCM 3.2
1452
         * SSR GLO Clock Correction
1453
         */
1454
4
        msg_name = "SSR GLO Clock Correction";
1455
4
        if (8 > rtcm->length) {
1456
            // not exactly: 8.125 + (9.37 * n)
1457
2
            bad_len = 8;
1458
2
            break;
1459
2
        }
1460
2
        break;
1461
1462
6
    case 1065:
1463
        /* RTCM 3.2
1464
         * SSR GLO Code Correction
1465
         */
1466
6
        msg_name = "SSR GLO ode Correction";
1467
6
        if (8 > rtcm->length) {
1468
            // not exactly: 8 + (1.25 * n) + (2.375 * ??)
1469
1
            bad_len = 8;
1470
1
            break;
1471
1
        }
1472
5
        break;
1473
1474
5
    case 1066:
1475
        /* RTCM 3.2
1476
         * SSR GLO Combined Orbit and Clock Correction
1477
         */
1478
3
        msg_name = "SSR GLO Combined Orbit and Clock Correction";
1479
3
        if (8 > rtcm->length) {
1480
            // not exactly: 8.125 + (25.5 * n)
1481
1
            bad_len = 8;
1482
1
            break;
1483
1
        }
1484
2
        break;
1485
1486
5
    case 1067:
1487
        /* RTCM 3.2
1488
         * SSR GLO URA
1489
         */
1490
5
        msg_name = "SSR GLO URA";
1491
5
        if (8 > rtcm->length) {
1492
            // not exactly: 8 + (1.375 * n)
1493
1
            bad_len = 8;
1494
1
            break;
1495
1
        }
1496
4
        break;
1497
1498
6
    case 1068:
1499
        /* RTCM 3.2
1500
         * SSR GPS High Rate Clock Correction
1501
         */
1502
6
        msg_name = "SSR GLO High Rate Clock Correction";
1503
6
        if (8 > rtcm->length) {
1504
            // not exactly: 8 + (3.375 * n)
1505
3
            bad_len = 8;
1506
3
            break;
1507
3
        }
1508
3
        break;
1509
1510
3
    case 1070:
1511
        /* RTCM 3.x
1512
         * Reserved for MSM
1513
         */
1514
1
        msg_name = "Reserved for MSM";
1515
1
        break;
1516
1517
5
    case 1071:
1518
        // RTCM 3.2
1519
5
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1520
5
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1521
5
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1522
5
        msg_name = "GPS MSM 1";
1523
5
        break;
1524
1525
7
    case 1072:
1526
        // RTCM 3.2
1527
7
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1528
7
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1529
7
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1530
7
        msg_name = "GPS MSM 2";
1531
7
        break;
1532
1533
13
    case 1073:
1534
        /* RTCM 3.2
1535
         * GPS Multi Signal Message 3
1536
         */
1537
13
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1538
13
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
1539
13
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1540
13
        msg_name = "GPS MSM 3";
1541
13
        break;
1542
1543
7
    case 1074:
1544
        /* RTCM 3.2
1545
         * GPS Multi Signal Message 4
1546
         */
1547
7
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1548
7
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
1549
7
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1550
7
        msg_name = "GPS MSM 4";
1551
7
        break;
1552
1553
4
    case 1075:
1554
        /* RTCM 3.2
1555
         * GPS Multi Signal Message 5
1556
         */
1557
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1558
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
1559
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1560
4
        msg_name = "GPS MSM 5";
1561
4
        break;
1562
1563
14
    case 1076:
1564
        /* RTCM 3.2
1565
         * GPS Multi Signal Message 6
1566
         */
1567
14
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1568
14
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
1569
14
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1570
14
        msg_name = "GPS MSM 6";
1571
14
        break;
1572
1573
4
    case 1077:
1574
        /* RTCM 3.2 - 1077
1575
         * GPS Multi Signal Message 7
1576
         * Full GPS pseudo-ranges, carrier phases, Doppler and
1577
         * signal strength (high resolution)
1578
         * min length 438
1579
         */
1580
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GPS;
1581
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
1582
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1583
4
        msg_name = "GPS MSM7";
1584
4
        break;
1585
1586
1
    case 1078:
1587
        /* RTCM 3.x
1588
         * Reserved for MSM
1589
         */
1590
1
        msg_name = "Reserved for MSM";
1591
1
        break;
1592
1593
1
    case 1079:
1594
        /* RTCM 3.x
1595
         * Reserved for MSM
1596
         */
1597
1
        msg_name = "Reserved for MSM";
1598
1
        break;
1599
1600
1
    case 1080:
1601
        /* RTCM 3.x
1602
         * Reserved for MSM
1603
         */
1604
1
        msg_name = "Reserved for MSM";
1605
1
        break;
1606
1607
3
    case 1081:
1608
        /* RTCM 3.2
1609
         * GLONASS Multi Signal Message 1
1610
         */
1611
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1612
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1613
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1614
3
        msg_name = "GLO MSM 1";
1615
3
        break;
1616
1617
2
    case 1082:
1618
        /* RTCM 3.2
1619
         * GLONASS Multi Signal Message 2
1620
         */
1621
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1622
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1623
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1624
2
        msg_name = "GLO MSM 2";
1625
2
        break;
1626
1627
3
    case 1083:
1628
        /* RTCM 3.2
1629
         * GLONASS Multi Signal Message 4
1630
         */
1631
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1632
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
1633
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1634
3
        msg_name = "GLO MSM 3";
1635
3
        break;
1636
1637
3
    case 1084:
1638
        /* RTCM 3.2
1639
         * GLONASS Multi Signal Message 4
1640
         */
1641
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1642
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
1643
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1644
3
        msg_name = "GLO MSM 4";
1645
3
        break;
1646
1647
5
    case 1085:
1648
        /* RTCM 3.2
1649
         * GLONASS Multi Signal Message 5
1650
         */
1651
5
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1652
5
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
1653
5
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1654
5
        msg_name = "GLO MSM 5";
1655
5
        break;
1656
1657
3
    case 1086:
1658
        /* RTCM 3.2
1659
         * GLONASS Multi Signal Message 6
1660
         */
1661
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1662
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
1663
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1664
3
        msg_name = "GLO MSM 6";
1665
3
        break;
1666
1667
7
    case 1087:
1668
        /* RTCM 3.2 - 1087
1669
         * GLONASS Multi Signal Message 7
1670
         * Full GLONASS pseudo-ranges, carrier phases, Doppler and
1671
         * signal strength (high resolution)
1672
         * length 417 or 427
1673
         */
1674
7
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GLO;
1675
7
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
1676
7
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1677
7
        msg_name = "GLO MSM 7";
1678
7
        break;
1679
1680
1
    case 1088:
1681
        /* RTCM 3.x
1682
         * Reserved for MSM
1683
         */
1684
1
        msg_name = "Reserved for MSM";
1685
1
        break;
1686
1687
1
    case 1089:
1688
        /* RTCM 3.x
1689
         * Reserved for MSM
1690
         */
1691
1
        msg_name = "Reserved for MSM";
1692
1
        break;
1693
1694
1
    case 1090:
1695
        /* RTCM 3.x
1696
         * Reserved for MSM
1697
         */
1698
1
        msg_name = "Reserved for MSM";
1699
1
        break;
1700
1701
4
    case 1091:
1702
        /* RTCM 3.2
1703
         * Galileo Multi Signal Message 1
1704
         */
1705
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1706
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1707
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1708
4
        msg_name = "GAL MSM 1";
1709
4
        break;
1710
1711
4
    case 1092:
1712
        /* RTCM 3.2
1713
         * Galileo Multi Signal Message 2
1714
         */
1715
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1716
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1717
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1718
4
        msg_name = "GAL MSM 2";
1719
4
        break;
1720
1721
5
    case 1093:
1722
        /* RTCM 3.2
1723
         * Galileo Multi Signal Message 3
1724
         */
1725
5
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1726
5
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
1727
5
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1728
5
        msg_name = "GAL MSM 3";
1729
5
        break;
1730
1731
5
    case 1094:
1732
        /* RTCM 3.2
1733
         * Galileo Multi Signal Message 4
1734
         */
1735
5
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1736
5
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
1737
5
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1738
5
        msg_name = "GAL MSM 4";
1739
5
        break;
1740
1741
2
    case 1095:
1742
        /* RTCM 3.2
1743
         * Galileo Multi Signal Message 5
1744
         */
1745
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1746
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
1747
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1748
2
        msg_name = "GAL MSM 5";
1749
2
        break;
1750
1751
4
    case 1096:
1752
        /* RTCM 3.2
1753
         * Galileo Multi Signal Message 6
1754
         */
1755
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1756
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
1757
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1758
4
        msg_name = "GAL MSM 6";
1759
4
        break;
1760
1761
2
    case 1097:
1762
        /* RTCM 3.2 - 1097
1763
         * Galileo Multi Signal Message 7
1764
         * Full Galileo pseudo-ranges, carrier phases, Doppler and
1765
         * signal strength (high resolution)
1766
         * length 96
1767
         */
1768
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_GAL;
1769
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
1770
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1771
2
        msg_name = "GAL MSM 7";
1772
2
        break;
1773
1774
1
    case 1098:
1775
        /* RTCM 3.x
1776
         * Reserved for MSM
1777
         */
1778
1
        msg_name = "Reserved for MSM";
1779
1
        break;
1780
1781
1
    case 1099:
1782
        /* RTCM 3.x
1783
         * Reserved for MSM
1784
         */
1785
1
        msg_name = "Reserved for MSM";
1786
1
        break;
1787
1788
1
    case 1100:
1789
        /* RTCM 3.x
1790
         * Reserved for MSM
1791
         */
1792
1
        msg_name = "Reserved for MSM";
1793
1
        break;
1794
1795
2
    case 1101:
1796
        /* RTCM 3.3
1797
         * SBAS Multi Signal Message 1
1798
         */
1799
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1800
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1801
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1802
2
        msg_name = "SBAS MSM 1";
1803
2
        break;
1804
1805
3
    case 1102:
1806
        /* RTCM 3.3
1807
         * SBAS Multi Signal Message 2
1808
         */
1809
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1810
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1811
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1812
3
        msg_name = "SBAS MSM 2";
1813
3
        break;
1814
1815
6
    case 1103:
1816
        /* RTCM 3.3
1817
         * SBAS Multi Signal Message 3
1818
         */
1819
6
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1820
6
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
1821
6
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1822
6
        msg_name = "SBAS MSM 3";
1823
6
        break;
1824
1825
4
    case 1104:
1826
        /* RTCM 3.3
1827
         * SBAS Multi Signal Message 4
1828
         */
1829
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1830
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
1831
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1832
4
        msg_name = "SBAS MSM 4";
1833
4
        break;
1834
1835
3
    case 1105:
1836
        /* RTCM 3.3
1837
         * SBAS Multi Signal Message 5
1838
         */
1839
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1840
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
1841
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1842
3
        msg_name = "SBAS MSM 5";
1843
3
        break;
1844
1845
3
    case 1106:
1846
        /* RTCM 3.3
1847
         * SBAS Multi Signal Message 6
1848
         */
1849
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1850
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
1851
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1852
3
        msg_name = "SBAS MSM 6";
1853
3
        break;
1854
1855
3
    case 1107:
1856
        /* RTCM 3.3 - 1107
1857
         * 'Multiple Signal Message
1858
         * Full SBAS pseudo-ranges, carrier phases, Doppler and
1859
         * signal strength (high resolution)
1860
         * length 96
1861
         */
1862
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_SBAS;
1863
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
1864
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1865
3
        msg_name = "SBAS MSM 7";
1866
3
        break;
1867
1868
1
    case 1108:
1869
        /* RTCM 3.x
1870
         * Reserved for MSM
1871
         */
1872
1
        msg_name = "Reserved for MSM";
1873
1
        break;
1874
1875
1
    case 1109:
1876
        /* RTCM 3.x
1877
         * Reserved for MSM
1878
         */
1879
1
        msg_name = "Reserved for MSM";
1880
1
        break;
1881
1882
1
    case 1110:
1883
        /* RTCM 3.x
1884
         * Reserved for MSM
1885
         */
1886
1
        msg_name = "Reserved for MSM";
1887
1
        break;
1888
1889
3
    case 1111:
1890
        /* RTCM 3.3
1891
         * QZSS Multi Signal Message 1
1892
         */
1893
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1894
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1895
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1896
3
        msg_name = "QZSS MSM 1";
1897
3
        break;
1898
1899
6
    case 1112:
1900
        /* RTCM 3.3
1901
         * QZSS Multi Signal Message 2
1902
         */
1903
6
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1904
6
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1905
6
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1906
6
        msg_name = "QZSS MSM 2";
1907
6
        break;
1908
1909
2
    case 1113:
1910
        /* RTCM 3.3
1911
         * QZSS Multi Signal Message 3
1912
         */
1913
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1914
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
1915
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1916
2
        msg_name = "QZSS MSM 3";
1917
2
        break;
1918
1919
2
    case 1114:
1920
        /* RTCM 3.3
1921
         * QZSS Multi Signal Message 4
1922
         */
1923
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1924
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
1925
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1926
2
        msg_name = "QZSS MSM 4";
1927
2
        break;
1928
1929
4
    case 1115:
1930
        /* RTCM 3.3
1931
         * QZSS Multi Signal Message 5
1932
         */
1933
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1934
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
1935
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1936
4
        msg_name = "QZSS MSM 5";
1937
4
        break;
1938
1939
2
    case 1116:
1940
        /* RTCM 3.3
1941
         * QZSS Multi Signal Message 6
1942
         */
1943
2
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1944
2
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
1945
2
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1946
2
        msg_name = "QZSS MSM 6";
1947
2
        break;
1948
1949
3
    case 1117:
1950
        /* RTCM 3.3
1951
         * QZSS Multi Signal Message 7
1952
         */
1953
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_QZSS;
1954
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
1955
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1956
3
        msg_name = "QZSS MSM 7";
1957
3
        break;
1958
1959
1
    case 1118:
1960
        /* RTCM 3.x
1961
         * Reserved for MSM
1962
         */
1963
1
        msg_name = "Reserved for MSM";
1964
1
        break;
1965
1966
1
    case 1119:
1967
        /* RTCM 3.x
1968
         * Reserved for MSM
1969
         */
1970
1
        msg_name = "Reserved for MSM";
1971
1
        break;
1972
1973
1
    case 1120:
1974
        /* RTCM 3.x
1975
         * Reserved for MSM
1976
         */
1977
1
        msg_name = "Reserved for MSM";
1978
1
        break;
1979
1980
4
    case 1121:
1981
        /* RTCM 3.2 A.1
1982
         * BD Multi Signal Message 1
1983
         */
1984
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
1985
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 1;
1986
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1987
4
        msg_name = "BD MSM 1";
1988
4
        break;
1989
1990
3
    case 1122:
1991
        /* RTCM 3.2 A.1
1992
         * BD Multi Signal Message 2
1993
         */
1994
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
1995
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 2;
1996
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
1997
3
        msg_name = "BD MSM 2";
1998
3
        break;
1999
2000
4
    case 1123:
2001
        /* RTCM 3.2 A.1
2002
         * BD Multi Signal Message 3
2003
         */
2004
4
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
2005
4
        rtcm->rtcmtypes.rtcm3_msm.msm = 3;
2006
4
        unknown = rtcm3_decode_msm(context, rtcm, buf);
2007
4
        msg_name = "BD MSM 3";
2008
4
        break;
2009
2010
8
    case 1124:
2011
        /* RTCM 3.2 A.1
2012
         * BD Multi Signal Message 4
2013
         */
2014
8
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
2015
8
        rtcm->rtcmtypes.rtcm3_msm.msm = 4;
2016
8
        unknown = rtcm3_decode_msm(context, rtcm, buf);
2017
8
        msg_name = "BD MSM 4";
2018
8
        break;
2019
2020
6
    case 1125:
2021
        /* RTCM 3.2 A.1
2022
         * BeiDou Multi Signal Message 5
2023
         */
2024
6
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
2025
6
        rtcm->rtcmtypes.rtcm3_msm.msm = 5;
2026
6
        unknown = rtcm3_decode_msm(context, rtcm, buf);
2027
6
        msg_name = "BD MSM 5";
2028
6
        break;
2029
2030
3
    case 1126:
2031
        /* RTCM 3.2 A.1
2032
         * BeiDou Multi Signal Message 6
2033
         */
2034
3
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
2035
3
        rtcm->rtcmtypes.rtcm3_msm.msm = 6;
2036
3
        unknown = rtcm3_decode_msm(context, rtcm, buf);
2037
3
        msg_name = "BD MSM 6";
2038
3
        break;
2039
2040
5
    case 1127:
2041
        /* RTCM 3.2 A.1
2042
         * BeiDou Multi Signal Message 7
2043
         */
2044
5
        rtcm->rtcmtypes.rtcm3_msm.gnssid = GNSSID_BD;
2045
5
        rtcm->rtcmtypes.rtcm3_msm.msm = 7;
2046
5
        unknown = rtcm3_decode_msm(context, rtcm, buf);
2047
5
        msg_name = "BD MSM 7";
2048
5
        break;
2049
2050
1
    case 1128:
2051
        /* RTCM 3.x
2052
         * Reserved for MSM
2053
         */
2054
1
        msg_name = "Reserved for MSM";
2055
1
        break;
2056
2057
1
    case 1229:
2058
        /* RTCM 3.x
2059
         * Reserved for MSM
2060
         */
2061
1
        msg_name = "Reserved for MSM";
2062
1
        break;
2063
2064
4
    case 1230:
2065
        /* RTCM 3.2
2066
         * GLONASS L1 and L2, C/A and P, Code-Phase Biases.
2067
         */
2068
4
        msg_name = "GLO L1 and L2 Code-Phase Biases";
2069
4
        unknown = false;
2070
4
        if (4 > rtcm->length) {
2071
            // not exactly: 32 + (16 * n), n <= 4
2072
            // but we see 12 and even 4??
2073
1
            bad_len = 4;
2074
1
            break;
2075
1
        }
2076
3
        rtcm->rtcmtypes.rtcm3_1230.station_id = ugrab(12);
2077
3
        rtcm->rtcmtypes.rtcm3_1230.bias_indicator = ugrab(1);
2078
3
        (void)ugrab(1);         // reserved
2079
3
        rtcm->rtcmtypes.rtcm3_1230.signals_mask = ugrab(3);
2080
        // actual mask order is undocumented...
2081
3
        if (1 & rtcm->rtcmtypes.rtcm3_1230.signals_mask) {
2082
1
            rtcm->rtcmtypes.rtcm3_1230.l1_ca_bias = ugrab(16);
2083
1
        }
2084
3
        if (2 & rtcm->rtcmtypes.rtcm3_1230.signals_mask) {
2085
1
            rtcm->rtcmtypes.rtcm3_1230.l1_p_bias = ugrab(16);
2086
1
        }
2087
3
        if (4 & rtcm->rtcmtypes.rtcm3_1230.signals_mask) {
2088
1
            rtcm->rtcmtypes.rtcm3_1230.l2_ca_bias = ugrab(16);
2089
1
        }
2090
3
        if (8 & rtcm->rtcmtypes.rtcm3_1230.signals_mask) {
2091
0
            rtcm->rtcmtypes.rtcm3_1230.l2_p_bias = ugrab(16);
2092
0
        }
2093
3
        break;
2094
2095
    // Message Types 4001 — 4060 Are Reserved
2096
2097
1
    case 4062:
2098
        /* RTCM 3.3
2099
         * Geely Proprietary
2100
         */
2101
1
        msg_name = "Geely Proprietary";
2102
1
        break;
2103
2104
1
    case 4063:
2105
        /* RTCM 3.3
2106
         * CHC Navigation (CHCNAV) Proprietary
2107
         */
2108
1
        msg_name = "CHC Navigation (CHCNAV) Proprietary";
2109
1
        break;
2110
2111
1
    case 4064:
2112
        /* RTCM 3.3
2113
         * NTLab Proprietary
2114
         */
2115
1
        msg_name = "NTLab Proprietary";
2116
1
        break;
2117
2118
1
    case 4065:
2119
        /* RTCM 3.3
2120
         * Allystar Technology (Shenzhen) Co. Ltd. Proprietary
2121
         *
2122
         * sub-id:
2123
         *    0    Reference stations PVT, requires MSM7.
2124
         *    1    Navigation PVT Solyution
2125
         *    2    Attitude Determination (multi antenna)
2126
         *    0x0a Raw Sensor measurements.
2127
         */
2128
1
        msg_name = "Allystar Technology (Shenzhen) Co. Ltd. Proprietary";
2129
1
        break;
2130
2131
1
    case 4066:
2132
        /* RTCM 3.3
2133
         * Lantmateriet Proprietary
2134
         */
2135
1
        msg_name = "Lantmateriet Proprietary";
2136
1
        break;
2137
2138
2
    case 4067:
2139
        /* RTCM 3.x
2140
         * China Transport telecommunications & Information Center Proprietary
2141
         */
2142
2
        msg_name = "China Transport telecommunications & Information "
2143
2
                       "Center Proprietary";
2144
2
        break;
2145
2146
1
    case 4068:
2147
        /* RTCM 3.3
2148
         * Qianxun Location Networks Co. Ltd Proprietary
2149
         */
2150
1
        msg_name = "Qianxun Location Networks Co. Ltd Proprietary";
2151
1
        break;
2152
2153
1
    case 4069:
2154
        /* RTCM 3.3
2155
         * VERIPOS Ltd Proprietary
2156
         */
2157
1
        msg_name = "VERIPOS Ltd Proprietary";
2158
1
        break;
2159
2160
1
    case 4070:
2161
        /* RTCM 3.3
2162
         * Wuhan MengXin Technology
2163
         */
2164
1
        msg_name = "Wuhan MengXin Technology Proprietary";
2165
1
        break;
2166
2167
1
    case 4071:
2168
        /* RTCM 3.3
2169
         * Wuhan Navigation and LBS
2170
         */
2171
1
        msg_name = "Wuhan Navigation and LBS Proprietary";
2172
1
        break;
2173
2174
1
    case 4072:
2175
        /* RTCM 3.x
2176
         * u-blox Proprietary
2177
         * Mitsubishi Electric Corp Proprietary
2178
         * 4072.0 Reference station PVT (u-blox proprietary)
2179
         * 4072.1 Additional reference station information (u-blox proprietary)
2180
         */
2181
1
        msg_name = "u-blox Proprietary";
2182
1
        break;
2183
2184
1
    case 4073:
2185
        /* RTCM 3.x
2186
         * Unicore Communications Proprietary
2187
         */
2188
1
        msg_name = "Alberding GmbH Proprietary";
2189
1
        break;
2190
2191
1
    case 4075:
2192
        /* RTCM 3.x
2193
         * Alberding GmbH Proprietary
2194
         */
2195
1
        msg_name = "Alberding GmbH Proprietary";
2196
1
        break;
2197
2198
5
    case 4076:
2199
        /* RTCM 3.x
2200
         * International GNSS Service Proprietary, www.igs.org
2201
         */
2202
5
        if (22 > rtcm->length) {
2203
            // need 76 bits, 9.5 bytes
2204
4
            bad_len = 22;
2205
4
            break;
2206
4
        }
2207
2208
1
        msg_name = "International GNSS Service Proprietary";
2209
1
        unknown = rtcm3_4076(context, rtcm, buf);
2210
1
        break;
2211
2212
1
    case 4077:
2213
        /* RTCM 3.x
2214
         * Hemisphere GNSS Proprietary
2215
         */
2216
1
        msg_name = "Hemisphere GNSS Proprietary";
2217
1
        break;
2218
2219
1
    case 4078:
2220
        /* RTCM 3.x
2221
         * ComNav Technology Proprietary
2222
         */
2223
1
        msg_name = "ComNav Technology Proprietary";
2224
1
        break;
2225
2226
1
    case 4079:
2227
        /* RTCM 3.x
2228
         * SubCarrier Systems Corp Proprietary
2229
         */
2230
1
        msg_name = "SubCarrier Systems Corp Proprietary";
2231
1
        break;
2232
2233
1
    case 4080:
2234
        /* RTCM 3.x
2235
         * NavCom Technology, Inc.
2236
         */
2237
1
        msg_name = "NavCom Technology, Inc.";
2238
1
        break;
2239
2240
1
    case 4081:
2241
        /* RTCM 3.x
2242
         * Seoul National Universtiry GNSS Lab Proprietary
2243
         */
2244
1
        msg_name = "Seoul National Universtiry GNSS Lab Proprietery";
2245
1
        break;
2246
2247
1
    case 4082:
2248
        /* RTCM 3.x
2249
         * Cooperative Research Centre for Spatial Information Proprietary
2250
         */
2251
1
        msg_name = "Cooperative Research Centre for Spatial Information "
2252
1
                       "Proprietary";
2253
1
        break;
2254
2255
1
    case 4083:
2256
        /* RTCM 3.x
2257
         * German Aerospace Center Proprietary
2258
         */
2259
1
        msg_name = "German Aerospace Center Proprietary";
2260
1
        break;
2261
2262
1
    case 4084:
2263
        /* RTCM 3.x
2264
         * Geodetics Inc Proprietary
2265
         */
2266
1
        msg_name = "Geodetics Inc Proprietary";
2267
1
        break;
2268
2269
1
    case 4085:
2270
        /* RTCM 3.x
2271
         * European GNSS Supervisory Authority Proprietary
2272
         */
2273
1
        msg_name = "European GNSS Supervisory Authority Proprietary";
2274
1
        break;
2275
2276
1
    case 4086:
2277
        /* RTCM 3.x
2278
         * InPosition GmbH Proprietary
2279
         */
2280
1
        msg_name = "InPosition GmbH Proprietary";
2281
1
        break;
2282
2283
1
    case 4087:
2284
        /* RTCM 3.x
2285
         * Fugro Proprietary
2286
         */
2287
1
        msg_name = "Fugro Proprietary";
2288
1
        break;
2289
2290
1
    case 4088:
2291
        /* RTCM 3.x
2292
         * IfEN GmbH Proprietary
2293
         */
2294
1
        msg_name = "IfEN GmbH Proprietary";
2295
1
        break;
2296
2297
1
    case 4089:
2298
        /* RTCM 3.x
2299
         * Septentrio Satellite Navigation Proprietary
2300
         */
2301
1
        msg_name = "Septentrio Satellite Navigation Proprietary";
2302
1
        break;
2303
2304
1
    case 4090:
2305
        /* RTCM 3.x
2306
         * Geo++ Proprietary
2307
         */
2308
1
        msg_name = "Geo++ Proprietary";
2309
1
        break;
2310
2311
1
    case 4091:
2312
        /* RTCM 3.x
2313
         * Topcon Positioning Systems Proprietary
2314
         */
2315
1
        msg_name = "Topcon Positioning Systems Proprietary";
2316
1
        break;
2317
2318
1
    case 4092:
2319
        /* RTCM 3.x
2320
         * Leica Geosystems Proprietary
2321
         */
2322
1
        msg_name = "Leica Geosystems Proprietary";
2323
1
        break;
2324
2325
1
    case 4093:
2326
        /* RTCM 3.x
2327
         * NovAtel Proprietary
2328
         */
2329
1
        msg_name = "NovAtel Pr.orietary";
2330
1
        break;
2331
2332
1
    case 4094:
2333
        /* RTCM 3.x
2334
         * Trimble Proprietary
2335
         */
2336
1
        msg_name = "Trimble Proprietary";
2337
1
        break;
2338
2339
2
    case 4095:
2340
        /* RTCM 3.x
2341
         * Ashtech/Magellan Proprietary
2342
         */
2343
2
        msg_name = "Ashtech/Magellan Proprietary";
2344
2
        break;
2345
2346
0
    case 63:
2347
        // dunno what this is.  Length 64
2348
0
        FALLTHROUGH
2349
134
    default:
2350
134
        break;
2351
1.35k
    }
2352
1.35k
#undef RANGEDIFF
2353
1.35k
#undef GPS_PSEUDORANGE
2354
1.35k
#undef sgrab
2355
1.35k
#undef ugrab
2356
1.35k
    if (0 != bad_len) {
2357
251
            GPSD_LOG(LOG_WARN, &context->errout,
2358
251
                     "RTCM3: type %d (%s) bad n %u length %u s/b %u\n",
2359
251
                     rtcm->type,  msg_name, n, rtcm->length, bad_len);
2360
251
            rtcm->length = 0;          // set to zero to prevent JSON decode
2361
251
            return;
2362
251
    }
2363
1.10k
    if (unknown) {
2364
        /*
2365
         * Leader bytes, message length, and checksum won't be copied.
2366
         * The first 12 bits of the copied payload will be the type field.
2367
         */
2368
301
        rtcm3_copy_string_field((char *)rtcm->rtcmtypes.data,
2369
301
                                sizeof(rtcm->rtcmtypes.data),
2370
301
                                buf + 3, rtcm->length);
2371
301
        GPSD_LOG(LOG_PROG, &context->errout,
2372
301
                 "RTCM3: %d (%s) Undecoded, length %u\n",
2373
301
                 rtcm->type, msg_name, rtcm->length);
2374
804
    } else {
2375
804
        GPSD_LOG(LOG_PROG, &context->errout,
2376
804
                 "RTCM3: %d (%s) length %u\n",
2377
804
                 rtcm->type, msg_name, rtcm->length);
2378
804
    }
2379
1.10k
}
2380
2381
// *INDENT-ON*
2382
2383
// vim: set expandtab shiftwidth=4