Coverage Report

Created: 2026-04-12 06:12

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