Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ubx-galileo_e1b_inav.c
Line
Count
Source
1
/* packet-ubx-galileo_e1b_inav.c
2
 * Dissection of Galileo E1-B I/NAV navigation messages
3
 * (as provided by UBX-RXM-SFRBX).
4
 *
5
 * By Timo Warns <timo.warns@gmail.com>
6
 * Copyright 2023 Timo Warns
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@unicom.net>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/conversation.h>
18
#include <epan/packet.h>
19
#include <epan/tfs.h>
20
#include <epan/unit_strings.h>
21
#include <proto.h>
22
#include <wmem_scopes.h>
23
#include <wsutil/array.h>
24
#include <wsutil/pint.h>
25
#include <wsutil/utf8_entities.h>
26
27
#include "packet-ubx.h"
28
#include "wsutil/wmem/wmem_core.h"
29
30
/*
31
 * Dissects Galileo E1-B I/NAV navigation messages
32
 * as encoded by UBX (in UBX-RXM-SFRBX messages).
33
 * Based on Galileo OS SIS ICD Issue 2.1
34
 */
35
36
const value_string DAY_NUMBER[] = {
37
    {0, "not defined"},
38
    {1, "Sunday"},
39
    {2, "Monday"},
40
    {3, "Tuesday"},
41
    {4, "Wednesday"},
42
    {5, "Thursday"},
43
    {6, "Friday"},
44
    {7, "Saturday"},
45
    {0, NULL},
46
};
47
48
static const value_string GAL_OSNMA_NMAS_CODE[] = {
49
    { 0, "Reserved"},
50
    { 1, "Test"},
51
    { 2, "Operational"},
52
    { 3, "Don't use"},
53
    { 0, NULL},
54
};
55
56
static const value_string GAL_OSNMA_CPKS_CODE[] = {
57
    { 0, "Reserved"},
58
    { 1, "Nominal"},
59
    { 2, "End of Chain (EOC)"},
60
    { 3, "Chain Revoked (CREV)"},
61
    { 4, "New Public Key (NPK)"},
62
    { 5, "Public Key Revoked (PKREV)"},
63
    { 6, "New Merkle Tree (NMT)"},
64
    { 7, "Alert Message (AM)"},
65
    { 0, NULL},
66
};
67
68
static const value_string GAL_OSNMA_NB_DP_CODE[] = {
69
    { 0, "Reserved"},
70
    { 1, "Reserved"},
71
    { 2, "Reserved"},
72
    { 3, "Reserved"},
73
    { 4, "Reserved"},
74
    { 5, "Reserved"},
75
    { 6, "Reserved"},
76
    { 7, "13"},
77
    { 8, "14"},
78
    { 9, "15"},
79
    {10, "16"},
80
    {11, "Reserved"},
81
    {12, "Reserved"},
82
    {13, "Reserved"},
83
    {14, "Reserved"},
84
    {15, "Reserved"},
85
    { 0, NULL},
86
};
87
88
static const value_string GAL_OSNMA_NB_DK_CODE[] = {
89
    { 0, "Reserved"},
90
    { 1, "7"},
91
    { 2, "8"},
92
    { 3, "9"},
93
    { 4, "10"},
94
    { 5, "11"},
95
    { 6, "12"},
96
    { 7, "13"},
97
    { 8, "14"},
98
    { 9, "Reserved"},
99
    {10, "Reserved"},
100
    {11, "Reserved"},
101
    {12, "Reserved"},
102
    {13, "Reserved"},
103
    {14, "Reserved"},
104
    {15, "Reserved"},
105
    { 0, NULL},
106
};
107
108
static const value_string GAL_OSNMA_NPKT_CODE[] = {
109
    { 0, "Reserved"},
110
    { 1, "ECDSA P-256"},
111
    { 2, "Reserved"},
112
    { 3, "ECDSA P-521"},
113
    { 4, "OSNMA Alert Message (OAM)"},
114
    { 5, "Reserved"},
115
    { 6, "Reserved"},
116
    { 7, "Reserved"},
117
    { 8, "Reserved"},
118
    { 9, "Reserved"},
119
    {10, "Reserved"},
120
    {11, "Reserved"},
121
    {12, "Reserved"},
122
    {13, "Reserved"},
123
    {14, "Reserved"},
124
    {15, "Reserved"},
125
    { 0, NULL},
126
};
127
128
static const value_string GAL_OSNMA_HF_CODE[] = {
129
    { 0, "SHA-256"},
130
    { 1, "Reserved"},
131
    { 2, "SHA3-256"},
132
    { 3, "Reserved"},
133
    { 0, NULL},
134
};
135
136
static const value_string GAL_OSNMA_MF_CODE[] = {
137
    { 0, "HMAC-SHA-256"},
138
    { 1, "CMAC-AES"},
139
    { 2, "Reserved"},
140
    { 3, "Reserved"},
141
    { 0, NULL},
142
};
143
144
static const value_string GAL_OSNMA_KS_CODE[] = {
145
    { 0, "96 bits"},
146
    { 1, "104 bits"},
147
    { 2, "112 bits"},
148
    { 3, "120 bits"},
149
    { 4, "128 bits"},
150
    { 5, "160 bits"},
151
    { 6, "192 bits"},
152
    { 7, "224 bits"},
153
    { 8, "256 bits"},
154
    { 9, "Reserved"},
155
    {10, "Reserved"},
156
    {11, "Reserved"},
157
    {12, "Reserved"},
158
    {13, "Reserved"},
159
    {14, "Reserved"},
160
    {15, "Reserved"},
161
    { 0, NULL},
162
};
163
0
static uint32_t ks2len(uint32_t ks) {
164
0
    if (ks <= 4) {
165
0
        return 12 + ks;
166
0
    }
167
0
    else if (ks <= 8) {
168
0
        return 20 + (ks-5) * 4;
169
0
    }
170
0
    else {
171
0
        return 0;
172
0
    }
173
0
}
174
175
static const value_string GAL_OSNMA_TS_CODE[] = {
176
    { 0, "Reserved"},
177
    { 1, "Reserved"},
178
    { 2, "Reserved"},
179
    { 3, "Reserved"},
180
    { 4, "Reserved"},
181
    { 5, "20 bits"},
182
    { 6, "24 bits"},
183
    { 7, "28 bits"},
184
    { 8, "32 bits"},
185
    { 9, "40 bits"},
186
    {10, "Reserved"},
187
    {11, "Reserved"},
188
    {12, "Reserved"},
189
    {13, "Reserved"},
190
    {14, "Reserved"},
191
    {15, "Reserved"},
192
    { 0, NULL},
193
};
194
195
static const value_string GAL_SAR_SHORT_RLM_MSG_CODE[] = {
196
    { 0, "Spare"},
197
    { 1, "Acknowledgement Service"},
198
    { 2, "Spare"},
199
    { 3, "Spare"},
200
    { 4, "Spare"},
201
    { 5, "Spare"},
202
    { 6, "Spare"},
203
    { 7, "Spare"},
204
    { 8, "Spare"},
205
    { 9, "Spare"},
206
    {10, "Spare"},
207
    {11, "Spare"},
208
    {12, "Spare"},
209
    {13, "Spare"},
210
    {14, "Spare"},
211
    {15, "Test Service"},
212
    { 0, NULL},
213
};
214
215
0
#define CONVERSATION_SAR_RLM 1
216
0
#define CONVERSATION_OSNMA_HKROOT_MACK 2
217
0
#define CONVERSATION_OSNMA_DSM 3
218
219
// Initialize the protocol and registered fields
220
static int proto_ubx_gal_inav;
221
222
static int hf_ubx_gal_inav_even_odd;
223
static int hf_ubx_gal_inav_page_type;
224
static int hf_ubx_gal_inav_type;
225
static int hf_ubx_gal_inav_data_122_67;
226
static int hf_ubx_gal_inav_data_66_17;
227
static int hf_ubx_gal_inav_data_16_1;
228
229
static int hf_ubx_gal_inav_osnma_hkroot;
230
static int hf_ubx_gal_inav_osnma_mack;
231
static int hf_ubx_gal_inav_osnma_nmas;
232
static int hf_ubx_gal_inav_osnma_cid;
233
static int hf_ubx_gal_inav_osnma_cpks;
234
static int hf_ubx_gal_inav_osnma_reserved;
235
static int hf_ubx_gal_inav_osnma_dsm_id;
236
static int hf_ubx_gal_inav_osnma_dsm_blk_id;
237
static int hf_ubx_gal_inav_osnma_dsm_blk;
238
static int hf_ubx_gal_inav_osnma_tag0;
239
static int hf_ubx_gal_inav_osnma_macseq;
240
static int hf_ubx_gal_inav_osnma_cop;
241
static int hf_ubx_gal_inav_osnma_tag;
242
static int hf_ubx_gal_inav_osnma_prn_d;
243
static int hf_ubx_gal_inav_osnma_adkd;
244
static int hf_ubx_gal_inav_osnma_key;
245
static int hf_ubx_gal_inav_osnma_padding;
246
static int hf_ubx_gal_inav_osnma_dsm_nb_dk;
247
static int hf_ubx_gal_inav_osnma_dsm_pkid;
248
static int hf_ubx_gal_inav_osnma_dsm_cidkr;
249
static int hf_ubx_gal_inav_osnma_dsm_reserved1;
250
static int hf_ubx_gal_inav_osnma_dsm_hf;
251
static int hf_ubx_gal_inav_osnma_dsm_mf;
252
static int hf_ubx_gal_inav_osnma_dsm_ks;
253
static int hf_ubx_gal_inav_osnma_dsm_ts;
254
static int hf_ubx_gal_inav_osnma_dsm_maclt;
255
static int hf_ubx_gal_inav_osnma_dsm_reserved2;
256
static int hf_ubx_gal_inav_osnma_dsm_wn_k;
257
static int hf_ubx_gal_inav_osnma_dsm_towh_k;
258
static int hf_ubx_gal_inav_osnma_dsm_alpha;
259
static int hf_ubx_gal_inav_osnma_dsm_kroot;
260
static int hf_ubx_gal_inav_osnma_dsm_ds;
261
static int hf_ubx_gal_inav_osnma_dsm_p_dk;
262
static int hf_ubx_gal_inav_osnma_dsm_nb_dp;
263
static int hf_ubx_gal_inav_osnma_dsm_mid;
264
static int hf_ubx_gal_inav_osnma_dsm_x_0_0;
265
static int hf_ubx_gal_inav_osnma_dsm_x_0_1;
266
static int hf_ubx_gal_inav_osnma_dsm_x_0_2;
267
static int hf_ubx_gal_inav_osnma_dsm_x_0_3;
268
static int hf_ubx_gal_inav_osnma_dsm_x_0_4;
269
static int hf_ubx_gal_inav_osnma_dsm_x_0_5;
270
static int hf_ubx_gal_inav_osnma_dsm_x_0_6;
271
static int hf_ubx_gal_inav_osnma_dsm_x_0_7;
272
static int hf_ubx_gal_inav_osnma_dsm_x_0_8;
273
static int hf_ubx_gal_inav_osnma_dsm_x_0_9;
274
static int hf_ubx_gal_inav_osnma_dsm_x_0_10;
275
static int hf_ubx_gal_inav_osnma_dsm_x_0_11;
276
static int hf_ubx_gal_inav_osnma_dsm_x_0_12;
277
static int hf_ubx_gal_inav_osnma_dsm_x_0_13;
278
static int hf_ubx_gal_inav_osnma_dsm_x_0_14;
279
static int hf_ubx_gal_inav_osnma_dsm_x_0_15;
280
static int hf_ubx_gal_inav_osnma_dsm_x_1_0;
281
static int hf_ubx_gal_inav_osnma_dsm_x_1_1;
282
static int hf_ubx_gal_inav_osnma_dsm_x_1_2;
283
static int hf_ubx_gal_inav_osnma_dsm_x_1_3;
284
static int hf_ubx_gal_inav_osnma_dsm_x_1_4;
285
static int hf_ubx_gal_inav_osnma_dsm_x_1_5;
286
static int hf_ubx_gal_inav_osnma_dsm_x_1_6;
287
static int hf_ubx_gal_inav_osnma_dsm_x_1_7;
288
static int hf_ubx_gal_inav_osnma_dsm_x_2_0;
289
static int hf_ubx_gal_inav_osnma_dsm_x_2_1;
290
static int hf_ubx_gal_inav_osnma_dsm_x_2_2;
291
static int hf_ubx_gal_inav_osnma_dsm_x_2_3;
292
static int hf_ubx_gal_inav_osnma_dsm_x_3_0;
293
static int hf_ubx_gal_inav_osnma_dsm_x_3_1;
294
static int hf_ubx_gal_inav_osnma_dsm_npkt;
295
static int hf_ubx_gal_inav_osnma_dsm_npkid;
296
static int hf_ubx_gal_inav_osnma_dsm_npk;
297
static int hf_ubx_gal_inav_osnma_dsm_p_dp;
298
299
static int hf_ubx_gal_inav_sar_start_bit;
300
static int hf_ubx_gal_inav_sar_long_rlm;
301
static int hf_ubx_gal_inav_sar_rlm_data;
302
static int hf_ubx_gal_inav_sar_beacon_id;
303
static int hf_ubx_gal_inav_sar_msg_code;
304
305
static int hf_ubx_gal_inav_spare;
306
static int hf_ubx_gal_inav_ssp;
307
static int hf_ubx_gal_inav_crc;
308
static int hf_ubx_gal_inav_tail;
309
static int hf_ubx_gal_inav_pad;
310
static int hf_ubx_gal_inav_reserved_1;
311
312
static int hf_ubx_gal_inav_word_type;
313
314
static int hf_ubx_gal_inav_word0;
315
static int hf_ubx_gal_inav_word0_time;
316
static int hf_ubx_gal_inav_word0_spare;
317
static int hf_ubx_gal_inav_word0_wn;
318
static int hf_ubx_gal_inav_word0_tow;
319
320
static int hf_ubx_gal_inav_word1;
321
static int hf_ubx_gal_inav_word1_iodnav;
322
static int hf_ubx_gal_inav_word1_t0e;
323
static int hf_ubx_gal_inav_word1_m0;
324
static int hf_ubx_gal_inav_word1_e;
325
static int hf_ubx_gal_inav_word1_sqrta;
326
static int hf_ubx_gal_inav_word1_reserved;
327
328
static int hf_ubx_gal_inav_word2;
329
static int hf_ubx_gal_inav_word2_iodnav;
330
static int hf_ubx_gal_inav_word2_omega0;
331
static int hf_ubx_gal_inav_word2_i0;
332
static int hf_ubx_gal_inav_word2_omega;
333
static int hf_ubx_gal_inav_word2_incl_angle_rate;
334
static int hf_ubx_gal_inav_word2_reserved;
335
336
static int hf_ubx_gal_inav_word3;
337
static int hf_ubx_gal_inav_word3_iodnav;
338
static int hf_ubx_gal_inav_word3_omega_rate;
339
static int hf_ubx_gal_inav_word3_delta_n;
340
static int hf_ubx_gal_inav_word3_c_uc;
341
static int hf_ubx_gal_inav_word3_c_us;
342
static int hf_ubx_gal_inav_word3_c_rc;
343
static int hf_ubx_gal_inav_word3_c_rs;
344
static int hf_ubx_gal_inav_word3_sisa_e1_e5b;
345
346
static int hf_ubx_gal_inav_word4;
347
static int hf_ubx_gal_inav_word4_iodnav;
348
static int hf_ubx_gal_inav_word4_svid;
349
static int hf_ubx_gal_inav_word4_c_ic;
350
static int hf_ubx_gal_inav_word4_c_is;
351
static int hf_ubx_gal_inav_word4_t_0c;
352
static int hf_ubx_gal_inav_word4_a_f0;
353
static int hf_ubx_gal_inav_word4_a_f1;
354
static int hf_ubx_gal_inav_word4_a_f2;
355
static int hf_ubx_gal_inav_word4_spare;
356
357
static int hf_ubx_gal_inav_word6;
358
static int hf_ubx_gal_inav_word6_a0;
359
static int hf_ubx_gal_inav_word6_a1;
360
static int hf_ubx_gal_inav_word6_delta_t_ls;
361
static int hf_ubx_gal_inav_word6_t_0t;
362
static int hf_ubx_gal_inav_word6_wn_0t;
363
static int hf_ubx_gal_inav_word6_wn_lsf;
364
static int hf_ubx_gal_inav_word6_dn;
365
static int hf_ubx_gal_inav_word6_delta_t_lsf;
366
static int hf_ubx_gal_inav_word6_tow;
367
static int hf_ubx_gal_inav_word6_spare;
368
369
static dissector_table_t ubx_gal_inav_word_dissector_table;
370
371
static int ett_ubx_gal_inav;
372
static int ett_ubx_gal_inav_word0;
373
static int ett_ubx_gal_inav_word1;
374
static int ett_ubx_gal_inav_word2;
375
static int ett_ubx_gal_inav_word3;
376
static int ett_ubx_gal_inav_word4;
377
static int ett_ubx_gal_inav_word6;
378
static int ett_ubx_gal_inav_osnma;
379
static int ett_ubx_gal_inav_osnma_hkroot_msg;
380
static int ett_ubx_gal_inav_osnma_mack_msg;
381
static int ett_ubx_gal_inav_osnma_mack_tag[9];
382
static int ett_ubx_gal_inav_osnma_dsm;
383
static int ett_ubx_gal_inav_sar;
384
static int ett_ubx_gal_inav_sar_rlm;
385
386
static const value_string GAL_PAGE_TYPE[] = {
387
    {0, "nominal"},
388
    {1, "alert"},
389
    {0, NULL},
390
};
391
392
static const value_string GAL_SSP[] = {
393
    {0x04, "SSP 1"},
394
    {0x2b, "SSP 2"},
395
    {0x2f, "SSP 3"},
396
    {0, NULL},
397
};
398
399
0
#define OSNMA_HKROOT_MACK_MSG_PARTS_NUM 15
400
0
#define OSNMA_HKROOT_MSG_LENGTH OSNMA_HKROOT_MACK_MSG_PARTS_NUM * 8 / 8
401
0
#define OSNMA_MACK_MSG_LENGTH OSNMA_HKROOT_MACK_MSG_PARTS_NUM * 32 / 8
402
403
typedef struct osnma_hkroot_mack_msg_part {
404
    uint32_t frame;
405
    uint8_t hkroot;
406
    uint32_t mack;
407
} osnma_hkroot_mack_msg_part;
408
409
0
#define OSNMA_DSM_BLK_LENGTH 13
410
0
#define OSNMA_DSM_BLK_NUM 15
411
412
typedef struct osnma_dsm_blk {
413
    bool set;
414
    uint8_t blk[OSNMA_DSM_BLK_LENGTH];
415
} osnma_dsm_blk;
416
417
0
#define SAR_LONG_RLM_PARTS_NUM 8
418
#define SAR_LONG_RLM_LENGTH (SAR_LONG_RLM_PARTS_NUM * 20 / 8)
419
0
#define SAR_SHORT_RLM_PARTS_NUM 4
420
0
#define SAR_SHORT_RLM_LENGTH (SAR_SHORT_RLM_PARTS_NUM * 20 / 8)
421
422
typedef struct sar_rlm_part {
423
    uint32_t frame;
424
    bool long_rlm;
425
    uint32_t rlm_data;
426
} sar_rlm_part;
427
428
/* Format A_0 for GST-UTC Conversion with 2^-30s resolution */
429
0
void fmt_a0(char *label, int64_t c) {
430
0
    snprintf(label, ITEM_LABEL_LENGTH, "%" PRId64 " * 2^-30s", c);
431
0
}
432
433
/* Format A_1 for GST-UTC Conversion with 2^-50s/s resolution */
434
0
void fmt_a1(char *label, int32_t c) {
435
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-50s/s", c);
436
0
}
437
438
/* Format t_0t for GST-UTC Conversion with 3600s resolution */
439
0
static void fmt_t_0t(char *label, uint32_t c) {
440
0
    snprintf(label, ITEM_LABEL_LENGTH, "%us", c * 3600);
441
0
}
442
443
/* Format clock correction (with scale factor 60) for
444
 * t_0c
445
 */
446
0
static void fmt_clk_correction(char *label, uint32_t c) {
447
0
    snprintf(label, ITEM_LABEL_LENGTH, "%u s", 60 * c);
448
0
}
449
450
/* Format radians (with 2^-29 scale factor) for
451
 * amplitude of harmonic correction terms
452
 */
453
0
void fmt_lat_correction(char *label, int32_t c) {
454
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-29 radians", c);
455
0
}
456
457
/* Format meters (with 2^-5 scale factor) for
458
 * amplitude of orbit correction terms
459
 */
460
0
static void fmt_orbit_correction(char *label, int16_t c) {
461
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-5 m", c);
462
0
}
463
464
/* Format semi-circles (with 2^-31 scale factor) for
465
 * - mean anomaly at reference time
466
 * - longitude of ascending node of orbital plane at weekly epoch
467
 * - inclination angle at reference time
468
 * - argument of perigee
469
 */
470
0
static void fmt_semi_circles(char *label, int32_t c) {
471
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-31 semi-circles", c);
472
0
}
473
474
/* Format rate of semi-circles (with 2^-43 scale factor) for
475
 * - inclination angle
476
 * - right ascension
477
 * - mean motion difference
478
 */
479
0
void fmt_semi_circles_rate(char *label, int32_t c) {
480
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-43 semi-circles/s", c);
481
0
}
482
483
/* Format SISA */
484
0
static void fmt_sisa(char *label, uint8_t i) {
485
0
    if (i <= 49) {
486
        // 0 cm to 49 cm with 1 cm resolution
487
0
        snprintf(label, ITEM_LABEL_LENGTH, "%u cm", i);
488
0
    }
489
0
    else if (i <= 74) {
490
        // 50 cm to 98 cm with 2 cm resolution
491
0
        snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 50 + ((i - 50) * 2));
492
0
    }
493
0
    else if (i <= 99) {
494
        // 100 cm to 196 cm with 4 cm resolution
495
0
        snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 100 + ((i - 75) * 4));
496
0
    }
497
0
    else if (i <= 125) {
498
        // 200 cm to 600 cm with 16 cm resolution
499
0
        snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 200 + ((i - 100) * 16));
500
0
    }
501
0
    else if (i <= 254) {
502
        // Spare
503
0
        snprintf(label, ITEM_LABEL_LENGTH, "Spare");
504
0
    }
505
0
    else { // i == 255
506
0
        snprintf(label, ITEM_LABEL_LENGTH, "No Accuracy Prediction Available (NAPA)");
507
0
    }
508
0
}
509
510
/* Format SV clock bias (with 2^-34 scale factor) for
511
 * a_f0
512
 */
513
0
static void fmt_sv_clk_bias(char *label, int32_t c) {
514
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-34 s", c);
515
0
}
516
517
/* Format SV clock drift (with 2^-46 scale factor) for
518
 * a_f1
519
 */
520
0
static void fmt_sv_clk_drift(char *label, int32_t c) {
521
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-46 s/s", c);
522
0
}
523
524
/* Format SV clock drift rate (with 2^-59 scale factor) for
525
 * a_f1
526
 */
527
0
static void fmt_sv_clk_drift_rate(char *label, int32_t c) {
528
0
    snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-59 s/s" UTF8_SUPERSCRIPT_TWO, c);
529
0
}
530
531
/* Format eccentricity */
532
0
static void fmt_e(char *label, uint64_t c) {
533
0
    snprintf(label, ITEM_LABEL_LENGTH, "%" PRIu64 " * 2^-33", c);
534
0
}
535
536
/* Format square root of the semi-major axis */
537
0
static void fmt_sqrt_a(char *label, uint64_t c) {
538
0
    snprintf(label, ITEM_LABEL_LENGTH, "%" PRIu64 " * 2^-19 " UTF8_SQUARE_ROOT "m", c);
539
0
}
540
541
/* Format ephemeris reference time */
542
0
static void fmt_t0e(char *label, uint32_t c) {
543
0
    c = c * 60;
544
0
    snprintf(label, ITEM_LABEL_LENGTH, "%ds", c);
545
0
}
546
547
/* Dissect Galileo E1-B I/NAV navigation message */
548
0
static int dissect_ubx_gal_inav(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
549
0
    tvbuff_t *next_tvb;
550
551
0
    bool complete_hkroot_mack = false;
552
0
    bool sar_start, sar_long_rlm;
553
0
    uint32_t inav_type = 0, even_page_type, odd_page_type, hkroot, sar_rlm_data;
554
0
    uint64_t mack;
555
0
    uint32_t dsm_id, dsm_blk_id, dsm_ks;
556
0
    uint64_t data_122_67 = 0, data_66_17 = 0, data_16_1 = 0;
557
0
    uint8_t *word, *hkroot_msg, *dsm_buf, *mack_msg;
558
0
    osnma_hkroot_mack_msg_part *osnma_hkroot_mack_msg_parts = NULL;
559
0
    osnma_dsm_blk *osnma_dsm_blks = NULL;
560
0
    sar_rlm_part *sar_rlm_parts = NULL;
561
0
    size_t i;
562
563
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Galileo E1-B I/NAV");
564
0
    col_clear(pinfo->cinfo, COL_INFO);
565
566
0
    proto_tree *gal_inav_tree = proto_tree_add_subtree(tree, tvb, 0, 32, ett_ubx_gal_inav, NULL, "Galileo E1-B I/NAV");
567
568
    // even page
569
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_even_odd, tvb, 0, 1, ENC_NA);
570
0
    proto_tree_add_item_ret_uint(gal_inav_tree, hf_ubx_gal_inav_page_type, tvb, 0, 1, ENC_NA, &even_page_type);
571
572
0
    if (even_page_type == 1) { // alert page
573
0
        proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_reserved_1,  tvb, 0, 15, ENC_NA);
574
0
    }
575
0
    else if (even_page_type == 0) { // nominal page
576
0
        proto_tree_add_item_ret_uint(gal_inav_tree,   hf_ubx_gal_inav_type,        tvb, 0,  1, ENC_NA,         &inav_type);
577
0
        proto_tree_add_item_ret_uint64(gal_inav_tree, hf_ubx_gal_inav_data_122_67, tvb, 0,  8, ENC_BIG_ENDIAN, &data_122_67);
578
0
        proto_tree_add_item_ret_uint64(gal_inav_tree, hf_ubx_gal_inav_data_66_17,  tvb, 8,  8, ENC_BIG_ENDIAN, &data_66_17);
579
0
    }
580
581
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_tail,            tvb, 14, 1, ENC_NA);
582
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_pad,             tvb, 15, 1, ENC_NA);
583
584
585
    // odd page
586
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_even_odd, tvb, 16, 1, ENC_NA);
587
0
    proto_tree_add_item_ret_uint(gal_inav_tree, hf_ubx_gal_inav_page_type, tvb, 16, 1, ENC_NA, &odd_page_type);
588
589
0
    if (odd_page_type == 1) { // alert page
590
0
        proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_reserved_1,  tvb, 16, 11, ENC_NA);
591
0
    }
592
0
    else if (odd_page_type == 0) { // nominal page
593
0
        uint8_t *svid = (uint8_t *) data;
594
595
0
        proto_tree_add_item_ret_uint64(gal_inav_tree, hf_ubx_gal_inav_data_16_1,   tvb, 16, 8, ENC_BIG_ENDIAN, &data_16_1);
596
597
0
        proto_tree *osnma_tree = proto_tree_add_subtree(gal_inav_tree, tvb, 18, 6, ett_ubx_gal_inav_osnma, NULL, "OSNMA");
598
0
        proto_tree_add_item_ret_uint(osnma_tree, hf_ubx_gal_inav_osnma_hkroot,  tvb, 18, 4, ENC_BIG_ENDIAN, &hkroot);
599
0
        proto_tree_add_item_ret_uint64(osnma_tree, hf_ubx_gal_inav_osnma_mack,  tvb, 18, 8, ENC_BIG_ENDIAN, &mack);
600
601
        // manage OSNMA HKROOT & MACK messages via conversations
602
0
        if (svid != NULL && even_page_type == 0 && (hkroot != 0 || mack != 0)) {
603
            // try to find already existing conversation
604
0
            conversation_element_t constellation = {.type = CE_INT, .int_val = GNSS_ID_GALILEO};
605
0
            conversation_element_t type = {.type = CE_INT, .int_val = CONVERSATION_OSNMA_HKROOT_MACK};
606
0
            conversation_element_t prn = {.type = CE_INT, .int_val = *svid};
607
0
            conversation_element_t end = {.type = CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_GNSS};
608
0
            conversation_element_t ce[4] = {constellation, type, prn, end};
609
0
            conversation_t *c = find_conversation_full(pinfo->num, ce);
610
611
0
            if (c == NULL && inav_type == 2) {
612
                // No conversation found, but the current Word Type is 2.
613
                // As Word Type 2 nominally starts a sub-frame, start a new conversation.
614
                // TODO: Detect a new sub-frame based on GST (or, at least, cross-check against GST).
615
0
                c = conversation_new_full(pinfo->num, ce);
616
617
0
                osnma_hkroot_mack_msg_parts = (osnma_hkroot_mack_msg_part *) wmem_alloc0_array(wmem_file_scope(), osnma_hkroot_mack_msg_part, OSNMA_HKROOT_MACK_MSG_PARTS_NUM);
618
619
0
                osnma_hkroot_mack_msg_parts[0].frame = pinfo->num;
620
0
                osnma_hkroot_mack_msg_parts[0].hkroot = hkroot;
621
0
                osnma_hkroot_mack_msg_parts[0].mack = (uint32_t) mack;
622
623
0
                conversation_add_proto_data(c, proto_ubx_gal_inav, osnma_hkroot_mack_msg_parts);
624
0
            }
625
0
            else if (c != NULL && inav_type == 2) {
626
                // Check whether the conversation found starts at the current frame.
627
                // (If not, a new conversation needs to be created as the Word Type is 2, which nominally indicates a new sub-frame.)
628
                // TODO: Detect a new sub-frame based on GST (or, at least, cross-check against GST).
629
0
                osnma_hkroot_mack_msg_parts = (osnma_hkroot_mack_msg_part *) conversation_get_proto_data(c, proto_ubx_gal_inav);
630
631
0
                if (osnma_hkroot_mack_msg_parts != NULL && osnma_hkroot_mack_msg_parts[0].frame != pinfo->num) {
632
                    // Separate conversation found, start a new one.
633
0
                    c = conversation_new_full(pinfo->num, ce);
634
635
0
                    osnma_hkroot_mack_msg_parts = (osnma_hkroot_mack_msg_part *) wmem_alloc0_array(wmem_file_scope(), osnma_hkroot_mack_msg_part, OSNMA_HKROOT_MACK_MSG_PARTS_NUM);
636
637
0
                    osnma_hkroot_mack_msg_parts[0].frame = pinfo->num;
638
0
                    osnma_hkroot_mack_msg_parts[0].hkroot = hkroot;
639
0
                    osnma_hkroot_mack_msg_parts[0].mack = (uint32_t) mack;
640
641
0
                    conversation_add_proto_data(c, proto_ubx_gal_inav, osnma_hkroot_mack_msg_parts);
642
0
                }
643
0
            }
644
0
            else if (c != NULL) {
645
                // Check whether packet data still needs to be added to the conversation.
646
0
                osnma_hkroot_mack_msg_parts = (osnma_hkroot_mack_msg_part *) conversation_get_proto_data(c, proto_ubx_gal_inav);
647
648
0
                if (osnma_hkroot_mack_msg_parts) {
649
                    // TODO: Detecting the slot of the HKROOT/MACK part should be based on GST.
650
                    // TODO: Cross-check whether identified slot matches nominal Word Type schedule.
651
0
                    for (i = 0; i < OSNMA_HKROOT_MACK_MSG_PARTS_NUM; i++) {
652
0
                        if (osnma_hkroot_mack_msg_parts[i].frame == 0) {
653
0
                            osnma_hkroot_mack_msg_parts[i].frame = pinfo->num;
654
0
                            osnma_hkroot_mack_msg_parts[i].hkroot = hkroot;
655
0
                            osnma_hkroot_mack_msg_parts[i].mack = (uint32_t) mack;
656
0
                            break;
657
0
                        }
658
0
                        else if (osnma_hkroot_mack_msg_parts[i].frame == pinfo->num) {
659
0
                            break;
660
0
                        }
661
0
                    }
662
0
                }
663
0
            }
664
665
            // display OSNMA HKROOT and MACK message if all parts are available
666
0
            if (c != NULL && osnma_hkroot_mack_msg_parts != NULL) {
667
0
                for (i = 0; i < OSNMA_HKROOT_MACK_MSG_PARTS_NUM; i++) {
668
0
                    if (osnma_hkroot_mack_msg_parts[i].frame == 0) {
669
0
                        break;
670
0
                    }
671
0
                }
672
673
0
                if (i == OSNMA_HKROOT_MACK_MSG_PARTS_NUM) {
674
                    // All parts of an OSNMA HKROOT & MACK message are available in the conversation.
675
0
                    complete_hkroot_mack = true;
676
677
                    // Now dissect them.
678
679
                    // reserve buffer for OSNMA HKROOT message
680
0
                    hkroot_msg = wmem_alloc(pinfo->pool, OSNMA_HKROOT_MSG_LENGTH);
681
682
                    // fill buffer with OSNMA HKROOT parts
683
0
                    for (i = 0; i < OSNMA_HKROOT_MACK_MSG_PARTS_NUM; i++) {
684
0
                        hkroot_msg[i] = osnma_hkroot_mack_msg_parts[i].hkroot;
685
0
                    }
686
687
0
                    tvbuff_t *osnma_hkroot_msg_tvb = tvb_new_child_real_data(tvb, (uint8_t *)hkroot_msg, OSNMA_HKROOT_MSG_LENGTH, OSNMA_HKROOT_MSG_LENGTH);
688
0
                    add_new_data_source(pinfo, osnma_hkroot_msg_tvb, "Galileo E1-B I/NAV OSNMA HKROOT Message");
689
690
                    // dissect OSNMA HKROOT message
691
0
                    proto_tree *osnma_hkroot_msg_tree = proto_tree_add_subtree(osnma_tree, osnma_hkroot_msg_tvb, 0, OSNMA_HKROOT_MSG_LENGTH, ett_ubx_gal_inav_osnma_hkroot_msg, NULL, "HKROOT Message (re-assembled)");
692
693
0
                    proto_tree_add_item(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_nmas,                osnma_hkroot_msg_tvb, 0, 1,  ENC_NA);
694
0
                    proto_tree_add_item(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_cid,                 osnma_hkroot_msg_tvb, 0, 1,  ENC_NA);
695
0
                    proto_tree_add_item(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_cpks,                osnma_hkroot_msg_tvb, 0, 1,  ENC_NA);
696
0
                    proto_tree_add_item(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_reserved,            osnma_hkroot_msg_tvb, 0, 1,  ENC_NA);
697
0
                    proto_tree_add_item_ret_uint(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_dsm_id,     osnma_hkroot_msg_tvb, 1, 1,  ENC_NA, &dsm_id);
698
0
                    proto_tree_add_item_ret_uint(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_dsm_blk_id, osnma_hkroot_msg_tvb, 1, 1,  ENC_NA, &dsm_blk_id);
699
0
                    proto_tree_add_item(osnma_hkroot_msg_tree, hf_ubx_gal_inav_osnma_dsm_blk,             osnma_hkroot_msg_tvb, 2, 13, ENC_NA);
700
701
702
                    // reserve buffer for OSNMA MACK message
703
0
                    mack_msg = wmem_alloc(pinfo->pool, OSNMA_MACK_MSG_LENGTH);
704
705
                    // fill buffer with OSNMA MACK parts
706
0
                    for (i = 0; i < OSNMA_HKROOT_MACK_MSG_PARTS_NUM; i++) {
707
0
                        phtonu32(&mack_msg[i * 4], osnma_hkroot_mack_msg_parts[i].mack);
708
0
                    }
709
710
0
                    tvbuff_t *osnma_mack_msg_tvb = tvb_new_child_real_data(tvb, (uint8_t *)mack_msg, OSNMA_MACK_MSG_LENGTH, OSNMA_MACK_MSG_LENGTH);
711
0
                    add_new_data_source(pinfo, osnma_mack_msg_tvb, "Galileo E1-B I/NAV OSNMA MACK Message");
712
713
                    // dissect OSNMA MACK message
714
0
                    proto_tree *osnma_mack_msg_tree = proto_tree_add_subtree(osnma_tree, osnma_mack_msg_tvb, 0, OSNMA_MACK_MSG_LENGTH, ett_ubx_gal_inav_osnma_mack_msg, NULL, "MACK Message (re-assembled)");
715
716
                    // TODO: The key and tag size should be determined based on DSM-KROOT.
717
                    // Assuming key size of 128 bits and tag size of 40 bits for now (being the sizes used by GAL).
718
0
                    uint32_t key_size = 128;
719
0
                    uint32_t tag_size = 40;
720
0
                    proto_tree_add_item(osnma_mack_msg_tree, hf_ubx_gal_inav_osnma_tag0,   osnma_mack_msg_tvb, 0,              tag_size/8, ENC_NA);
721
0
                    proto_tree_add_item(osnma_mack_msg_tree, hf_ubx_gal_inav_osnma_macseq, osnma_mack_msg_tvb, tag_size/8,     2,          ENC_BIG_ENDIAN);
722
0
                    proto_tree_add_item(osnma_mack_msg_tree, hf_ubx_gal_inav_osnma_cop,    osnma_mack_msg_tvb, tag_size/8 + 1, 1,          ENC_NA);
723
724
0
                    uint32_t no_tags = (480 - key_size) / (tag_size + 16);
725
0
                    for (i = 0; i < no_tags - 1; i++) {
726
0
                        proto_tree *osnma_mack_tag_tree = proto_tree_add_subtree(osnma_mack_msg_tree, osnma_mack_msg_tvb, (((uint32_t)i + 1) * (tag_size + 16))/8, (tag_size + 16) / 8, ett_ubx_gal_inav_osnma_mack_tag[i], NULL, "MACK Tag");
727
0
                        proto_tree_add_item(osnma_mack_tag_tree, hf_ubx_gal_inav_osnma_tag,   osnma_mack_msg_tvb, (((uint32_t)i + 1) * (tag_size + 16))/8,                tag_size/8, ENC_NA);
728
0
                        proto_tree_add_item(osnma_mack_tag_tree, hf_ubx_gal_inav_osnma_prn_d, osnma_mack_msg_tvb, (((uint32_t)i + 1) * (tag_size + 16) + tag_size)/8,     1,          ENC_NA);
729
0
                        proto_tree_add_item(osnma_mack_tag_tree, hf_ubx_gal_inav_osnma_adkd,  osnma_mack_msg_tvb, (((uint32_t)i + 1) * (tag_size + 16) + tag_size)/8 + 1, 1,          ENC_NA);
730
0
                        proto_tree_add_item(osnma_mack_tag_tree, hf_ubx_gal_inav_osnma_cop,   osnma_mack_msg_tvb, (((uint32_t)i + 1) * (tag_size + 16) + tag_size)/8 + 1, 1,          ENC_NA);
731
0
                    }
732
733
0
                    proto_tree_add_item(osnma_mack_msg_tree, hf_ubx_gal_inav_osnma_key,     osnma_mack_msg_tvb, (no_tags * (tag_size + 16))/8,            key_size/8, ENC_NA);
734
0
                    proto_tree_add_item(osnma_mack_msg_tree, hf_ubx_gal_inav_osnma_padding, osnma_mack_msg_tvb, (no_tags * (tag_size + 16) + key_size)/8, OSNMA_MACK_MSG_LENGTH - (no_tags * (tag_size + 16) + key_size)/8, ENC_NA);
735
0
                }
736
0
            }
737
0
        }
738
739
        // manage OSNMA DSM via conversations (if a HKROOT message was re-assembled)
740
0
        if (complete_hkroot_mack) {
741
            // try to find already existing conversation
742
0
            conversation_element_t constellation = {.type = CE_INT, .int_val = GNSS_ID_GALILEO};
743
0
            conversation_element_t type = {.type = CE_INT, .int_val = CONVERSATION_OSNMA_DSM};
744
0
            conversation_element_t dsm = {.type = CE_INT, .int_val = dsm_id};
745
0
            conversation_element_t end = {.type = CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_GNSS};
746
0
            conversation_element_t ce[4] = {constellation, type, dsm, end};
747
0
            conversation_t *c = find_conversation_full(pinfo->num, ce);
748
749
            // TODO: Add logic to detect and manage DSM ID roll-over
750
0
            if (c == NULL) {
751
                // No conversation found. Start a new one.
752
0
                c = conversation_new_full(pinfo->num, ce);
753
754
0
                osnma_dsm_blks = (osnma_dsm_blk *) wmem_alloc0_array(wmem_file_scope(), osnma_dsm_blk, OSNMA_DSM_BLK_NUM);
755
756
0
                conversation_add_proto_data(c, proto_ubx_gal_inav, osnma_dsm_blks);
757
0
            }
758
0
            else {
759
0
                osnma_dsm_blks = (osnma_dsm_blk *) conversation_get_proto_data(c, proto_ubx_gal_inav);
760
0
            }
761
762
0
            if (osnma_dsm_blks != NULL) {
763
764
                // store block
765
0
                osnma_dsm_blks[dsm_blk_id].set = true;
766
0
                memcpy(osnma_dsm_blks[dsm_blk_id].blk, &hkroot_msg[2], OSNMA_DSM_BLK_LENGTH);
767
768
                // If first block of a DSM has been received, continue processing.
769
0
                if (osnma_dsm_blks[0].set && 0 < osnma_dsm_blks[0].blk[0]) {
770
771
                    // Count the number of sequential blocks received.
772
0
                    uint8_t dsm_blk_count = 0;
773
0
                    for (i = 0; i < OSNMA_DSM_BLK_NUM; i++) {
774
0
                        if (osnma_dsm_blks[i].set) {
775
0
                            dsm_blk_count++;
776
0
                        }
777
0
                        else {
778
0
                            break;
779
0
                        }
780
0
                    }
781
782
                    // Compare number of received blocks against NB_DP / NB_DK in block 0.
783
0
                    if (dsm_blk_count == (osnma_dsm_blks[0].blk[0] >> 4) + 6) {
784
                        // All blocks for a DSM have been received.
785
                        // Now dissect it.
786
787
0
                        dsm_buf = wmem_alloc(pinfo->pool, dsm_blk_count * OSNMA_DSM_BLK_LENGTH);
788
0
                        for (i = 0; i < dsm_blk_count; i++) {
789
0
                            memcpy(&dsm_buf[i * OSNMA_DSM_BLK_LENGTH], osnma_dsm_blks[i].blk, OSNMA_DSM_BLK_LENGTH);
790
0
                        }
791
0
                        tvbuff_t *osnma_dsm_tvb = tvb_new_child_real_data(tvb, (uint8_t *)dsm_buf, dsm_blk_count * OSNMA_DSM_BLK_LENGTH, dsm_blk_count * OSNMA_DSM_BLK_LENGTH);
792
0
                        add_new_data_source(pinfo, osnma_dsm_tvb, "Galileo E1-B I/NAV OSNMA DSM");
793
794
795
0
                        if (dsm_id < 12) {
796
                            // dissect DSM-KROOT
797
0
                            uint32_t dk_len = dsm_blk_count * OSNMA_DSM_BLK_LENGTH;
798
799
0
                            proto_tree *osnma_dsm_tree = proto_tree_add_subtree(osnma_tree, osnma_dsm_tvb, 0, dk_len, ett_ubx_gal_inav_osnma_dsm, NULL, "DSM-KROOT (re-assembled)");
800
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_nb_dk,     osnma_dsm_tvb,  0,  1, ENC_NA);
801
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_pkid,      osnma_dsm_tvb,  0,  1, ENC_NA);
802
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_cidkr,     osnma_dsm_tvb,  1,  1, ENC_NA);
803
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_reserved1, osnma_dsm_tvb,  1,  1, ENC_NA);
804
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_hf,        osnma_dsm_tvb,  1,  1, ENC_NA);
805
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_mf,        osnma_dsm_tvb,  1,  1, ENC_NA);
806
0
                            proto_tree_add_item_ret_uint(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_ks, osnma_dsm_tvb, 2, 1, ENC_NA, &dsm_ks);
807
0
                            uint32_t ks_len = ks2len(dsm_ks);
808
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_ts,        osnma_dsm_tvb,  2,  1, ENC_NA);
809
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_maclt,     osnma_dsm_tvb,  3,  1, ENC_NA);
810
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_reserved2, osnma_dsm_tvb,  4,  1, ENC_NA);
811
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_wn_k,      osnma_dsm_tvb,  4,  2, ENC_BIG_ENDIAN);
812
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_towh_k,    osnma_dsm_tvb,  6,  1, ENC_NA);
813
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_alpha,     osnma_dsm_tvb,  7,  6, ENC_NA);
814
0
                            if (ks_len > 0) {
815
                                // TODO: The length of the digital signature should be derived from the DSM-PKR NPKT with matching PKID.
816
0
                                uint32_t ds_len = 64;
817
0
                                uint32_t p_dk_len = dk_len - 13 - ks_len - ds_len;
818
819
0
                                proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_kroot, osnma_dsm_tvb, 13,                   ks_len,   ENC_NA);
820
0
                                proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_ds,    osnma_dsm_tvb, 13 + ks_len,          ds_len,   ENC_NA);
821
0
                                proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_p_dk,  osnma_dsm_tvb, 13 + ks_len + ds_len, p_dk_len, ENC_NA);
822
0
                            }
823
0
                        }
824
0
                        else {
825
                            // dissect DSM-PKR
826
0
                            uint32_t dsm_nb_dp, dsm_mid, dsm_npkt, l_npk, l_pdp;
827
828
0
                            proto_tree *osnma_dsm_tree = proto_tree_add_subtree(osnma_tree, osnma_dsm_tvb, 0, dsm_blk_count * OSNMA_DSM_BLK_LENGTH, ett_ubx_gal_inav_osnma_dsm, NULL, "DSM-PKR (re-assembled)");
829
0
                            proto_tree_add_item_ret_uint(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_nb_dp, osnma_dsm_tvb, 0, 1, ENC_NA, &dsm_nb_dp);
830
0
                            proto_tree_add_item_ret_uint(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_mid,   osnma_dsm_tvb, 0, 1, ENC_NA, &dsm_mid);
831
832
0
                            switch (dsm_mid) {
833
0
                                case 0:
834
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_1,  osnma_dsm_tvb,  1, 32, ENC_NA);
835
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_1,  osnma_dsm_tvb, 33, 32, ENC_NA);
836
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_1,  osnma_dsm_tvb, 65, 32, ENC_NA);
837
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
838
0
                                    break;
839
0
                                case 1:
840
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_0,  osnma_dsm_tvb,  1, 32, ENC_NA);
841
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_1,  osnma_dsm_tvb, 33, 32, ENC_NA);
842
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_1,  osnma_dsm_tvb, 65, 32, ENC_NA);
843
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
844
0
                                    break;
845
0
                                case 2:
846
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_3,  osnma_dsm_tvb,  1, 32, ENC_NA);
847
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_0,  osnma_dsm_tvb, 33, 32, ENC_NA);
848
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_1,  osnma_dsm_tvb, 65, 32, ENC_NA);
849
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
850
0
                                    break;
851
0
                                case 3:
852
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_2,  osnma_dsm_tvb,  1, 32, ENC_NA);
853
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_0,  osnma_dsm_tvb, 33, 32, ENC_NA);
854
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_1,  osnma_dsm_tvb, 65, 32, ENC_NA);
855
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
856
0
                                    break;
857
0
                                case 4:
858
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_5,  osnma_dsm_tvb,  1, 32, ENC_NA);
859
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_3,  osnma_dsm_tvb, 33, 32, ENC_NA);
860
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_0,  osnma_dsm_tvb, 65, 32, ENC_NA);
861
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
862
0
                                    break;
863
0
                                case 5:
864
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_4,  osnma_dsm_tvb,  1, 32, ENC_NA);
865
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_3,  osnma_dsm_tvb, 33, 32, ENC_NA);
866
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_0,  osnma_dsm_tvb, 65, 32, ENC_NA);
867
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
868
0
                                    break;
869
0
                                case 6:
870
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_7,  osnma_dsm_tvb,  1, 32, ENC_NA);
871
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_2,  osnma_dsm_tvb, 33, 32, ENC_NA);
872
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_0,  osnma_dsm_tvb, 65, 32, ENC_NA);
873
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
874
0
                                    break;
875
0
                                case 7:
876
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_6,  osnma_dsm_tvb,  1, 32, ENC_NA);
877
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_2,  osnma_dsm_tvb, 33, 32, ENC_NA);
878
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_0,  osnma_dsm_tvb, 65, 32, ENC_NA);
879
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_1,  osnma_dsm_tvb, 97, 32, ENC_NA);
880
0
                                    break;
881
0
                                case 8:
882
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_9,  osnma_dsm_tvb,  1, 32, ENC_NA);
883
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_5,  osnma_dsm_tvb, 33, 32, ENC_NA);
884
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_3,  osnma_dsm_tvb, 65, 32, ENC_NA);
885
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
886
0
                                    break;
887
0
                                case 9:
888
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_8,  osnma_dsm_tvb,  1, 32, ENC_NA);
889
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_5,  osnma_dsm_tvb, 33, 32, ENC_NA);
890
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_3,  osnma_dsm_tvb, 65, 32, ENC_NA);
891
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
892
0
                                    break;
893
0
                                case 10:
894
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_11, osnma_dsm_tvb,  1, 32, ENC_NA);
895
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_4,  osnma_dsm_tvb, 33, 32, ENC_NA);
896
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_3,  osnma_dsm_tvb, 65, 32, ENC_NA);
897
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
898
0
                                    break;
899
0
                                case 11:
900
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_10, osnma_dsm_tvb,  1, 32, ENC_NA);
901
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_4,  osnma_dsm_tvb, 33, 32, ENC_NA);
902
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_3,  osnma_dsm_tvb, 65, 32, ENC_NA);
903
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
904
0
                                    break;
905
0
                                case 12:
906
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_13, osnma_dsm_tvb,  1, 32, ENC_NA);
907
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_7,  osnma_dsm_tvb, 33, 32, ENC_NA);
908
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_2,  osnma_dsm_tvb, 65, 32, ENC_NA);
909
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
910
0
                                    break;
911
0
                                case 13:
912
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_12, osnma_dsm_tvb,  1, 32, ENC_NA);
913
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_7,  osnma_dsm_tvb, 33, 32, ENC_NA);
914
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_2,  osnma_dsm_tvb, 65, 32, ENC_NA);
915
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
916
0
                                    break;
917
0
                                case 14:
918
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_15, osnma_dsm_tvb,  1, 32, ENC_NA);
919
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_6,  osnma_dsm_tvb, 33, 32, ENC_NA);
920
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_2,  osnma_dsm_tvb, 65, 32, ENC_NA);
921
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
922
0
                                    break;
923
0
                                case 15:
924
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_0_14, osnma_dsm_tvb,  1, 32, ENC_NA);
925
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_1_6,  osnma_dsm_tvb, 33, 32, ENC_NA);
926
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_2_2,  osnma_dsm_tvb, 65, 32, ENC_NA);
927
0
                                    proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_x_3_0,  osnma_dsm_tvb, 97, 32, ENC_NA);
928
0
                                    break;
929
0
                                default:
930
0
                                    break;
931
0
                            }
932
933
0
                            proto_tree_add_item_ret_uint(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_npkt,  osnma_dsm_tvb, 129, 1, ENC_NA, &dsm_npkt);
934
0
                            proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_npkid, osnma_dsm_tvb, 129, 1, ENC_NA);
935
936
                            // compute field lengths
937
0
                            if (7 <= dsm_nb_dp && dsm_nb_dp <= 10 && (dsm_npkt == 1 || dsm_npkt == 3 || dsm_npkt == 4)) {
938
0
                                if (dsm_npkt == 1) { // ECDSA P-256
939
0
                                    l_npk = 264;
940
0
                                }
941
0
                                else if (dsm_npkt == 4) { // ECDSA P-521
942
0
                                    l_npk = 536;
943
0
                                }
944
0
                                else { // OSNMA Alert Message
945
0
                                    l_npk = ((dsm_nb_dp + 6) * 104) - 1040; // = l_PK_OAM
946
0
                                }
947
948
0
                                l_pdp = ((dsm_nb_dp + 6) * 104) - 1040 - l_npk;
949
950
0
                                proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_npk,  osnma_dsm_tvb, 130,               l_npk / 8, ENC_NA);
951
0
                                proto_tree_add_item(osnma_dsm_tree, hf_ubx_gal_inav_osnma_dsm_p_dp, osnma_dsm_tvb, 130 + (l_npk / 8), l_pdp / 8, ENC_NA);
952
0
                            }
953
0
                        }
954
0
                    }
955
0
                }
956
0
            }
957
0
        }
958
959
0
        proto_tree *sar_tree = proto_tree_add_subtree(gal_inav_tree, tvb, 23, 4, ett_ubx_gal_inav_sar, NULL, "SAR");
960
0
        proto_tree_add_item_ret_boolean(sar_tree, hf_ubx_gal_inav_sar_start_bit, tvb, 23, 4, ENC_BIG_ENDIAN, &sar_start);
961
0
        proto_tree_add_item_ret_boolean(sar_tree, hf_ubx_gal_inav_sar_long_rlm,  tvb, 23, 4, ENC_BIG_ENDIAN, &sar_long_rlm);
962
0
        proto_tree_add_item_ret_uint(sar_tree, hf_ubx_gal_inav_sar_rlm_data,     tvb, 23, 4, ENC_BIG_ENDIAN, &sar_rlm_data);
963
964
        // manage SAR RLM parts via conversations
965
0
        if (svid != NULL) {
966
967
            // try to find already existing conversation
968
0
            conversation_element_t constellation = {.type = CE_INT, .int_val = GNSS_ID_GALILEO};
969
0
            conversation_element_t type = {.type = CE_INT, .int_val = CONVERSATION_SAR_RLM};
970
0
            conversation_element_t prn = {.type = CE_INT, .int_val = *svid};
971
0
            conversation_element_t end = {.type = CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_GNSS};
972
0
            conversation_element_t ce[4] = {constellation, type, prn, end};
973
0
            conversation_t *c = find_conversation_full(pinfo->num, ce);
974
975
0
            if (c == NULL && sar_start) {
976
                // No conversation found. As the start bit is set, start a new one.
977
0
                c = conversation_new_full(pinfo->num, ce);
978
979
0
                sar_rlm_parts = (sar_rlm_part *) wmem_alloc0_array(wmem_file_scope(), sar_rlm_part, sar_long_rlm ? SAR_LONG_RLM_PARTS_NUM : SAR_SHORT_RLM_PARTS_NUM);
980
981
0
                sar_rlm_parts[0].frame = pinfo->num;
982
0
                sar_rlm_parts[0].long_rlm = sar_long_rlm;
983
0
                sar_rlm_parts[0].rlm_data = sar_rlm_data;
984
985
0
                conversation_add_proto_data(c, proto_ubx_gal_inav, sar_rlm_parts);
986
0
            }
987
0
            else if (c != NULL && sar_start) {
988
                // Check whether the conversation found starts at the
989
                // current frame. (If not, a new conversation needs to be
990
                // created as the start bit is set.
991
0
                sar_rlm_parts = (sar_rlm_part *) conversation_get_proto_data(c, proto_ubx_gal_inav);
992
993
0
                if (sar_rlm_parts != NULL && sar_rlm_parts[0].frame != pinfo->num) {
994
                    // Separate conversation found, start a new one.
995
0
                    c = conversation_new_full(pinfo->num, ce);
996
997
0
                    sar_rlm_parts = (sar_rlm_part *) wmem_alloc0_array(wmem_file_scope(), sar_rlm_part, sar_long_rlm ? SAR_LONG_RLM_PARTS_NUM : SAR_SHORT_RLM_PARTS_NUM);
998
999
0
                    sar_rlm_parts[0].frame = pinfo->num;
1000
0
                    sar_rlm_parts[0].long_rlm = sar_long_rlm;
1001
0
                    sar_rlm_parts[0].rlm_data = sar_rlm_data;
1002
1003
0
                    conversation_add_proto_data(c, proto_ubx_gal_inav, sar_rlm_parts);
1004
0
                }
1005
1006
0
            }
1007
0
            else if (c != NULL) {
1008
                // Check whether packet data still needs to be added to the conversation.
1009
0
                sar_rlm_parts = (sar_rlm_part *) conversation_get_proto_data(c, proto_ubx_gal_inav);
1010
1011
0
                if (sar_rlm_parts != NULL && sar_rlm_parts[0].long_rlm == sar_long_rlm) {
1012
0
                    for (i = 0; i < (sar_long_rlm ? SAR_LONG_RLM_PARTS_NUM : SAR_SHORT_RLM_PARTS_NUM); i++) {
1013
0
                        if (sar_rlm_parts[i].frame == 0) {
1014
0
                            sar_rlm_parts[i].frame = pinfo->num;
1015
0
                            sar_rlm_parts[i].long_rlm = sar_long_rlm;
1016
0
                            sar_rlm_parts[i].rlm_data = sar_rlm_data;
1017
0
                            break;
1018
0
                        }
1019
0
                        else if (sar_rlm_parts[i].frame == pinfo->num) {
1020
0
                            break;
1021
0
                        }
1022
0
                    }
1023
0
                }
1024
0
            }
1025
1026
            // display SAR RLM if all parts are available
1027
0
            if (c != NULL && sar_rlm_parts != NULL) {
1028
0
                for (i = 0; i < (sar_long_rlm ? SAR_LONG_RLM_PARTS_NUM : SAR_SHORT_RLM_PARTS_NUM); i++) {
1029
0
                    if (sar_rlm_parts[i].frame == 0) {
1030
0
                        break;
1031
0
                    }
1032
0
                }
1033
1034
0
                if (!sar_long_rlm && i == SAR_SHORT_RLM_PARTS_NUM) {
1035
                    // All parts of a Short-RLM are available in the conversation.
1036
                    // Now dissect it.
1037
1038
                    // reserve buffer for short RLM
1039
0
                    uint8_t *buf = wmem_alloc(pinfo->pool, SAR_SHORT_RLM_LENGTH);
1040
1041
                    // fill buffer with RLM parts
1042
0
                    phtonu32(buf, (sar_rlm_parts[0].rlm_data << 12) | (sar_rlm_parts[1].rlm_data >> 8));
1043
0
                    phtonu32(buf + 4, (sar_rlm_parts[1].rlm_data << 24) | (sar_rlm_parts[2].rlm_data << 4) | (sar_rlm_parts[3].rlm_data >> 16));
1044
0
                    phtonu16(buf + 8, (sar_rlm_parts[3].rlm_data & 0xffff));
1045
1046
0
                    tvbuff_t *rlm_tvb = tvb_new_child_real_data(tvb, (uint8_t *)buf, SAR_SHORT_RLM_LENGTH, SAR_SHORT_RLM_LENGTH);
1047
0
                    add_new_data_source(pinfo, rlm_tvb, "Galileo E1-B I/NAV SAR Short-RLM");
1048
1049
                    // dissect RLM
1050
0
                    proto_tree *sar_rlm_tree = proto_tree_add_subtree(sar_tree, rlm_tvb, 0, SAR_SHORT_RLM_LENGTH, ett_ubx_gal_inav_sar_rlm, NULL, "Short-RLM (re-assembled)");
1051
1052
0
                    proto_tree_add_item(sar_rlm_tree, hf_ubx_gal_inav_sar_beacon_id, rlm_tvb, 0, 8, ENC_BIG_ENDIAN);
1053
0
                    proto_tree_add_item(sar_rlm_tree, hf_ubx_gal_inav_sar_msg_code,  rlm_tvb, 6, 4, ENC_BIG_ENDIAN);
1054
0
                }
1055
0
                else if (sar_long_rlm && i == SAR_LONG_RLM_PARTS_NUM) {
1056
                    // All parts of a Long-RLM are available in the conversation.
1057
                    // TODO: Now dissect it.
1058
0
                }
1059
0
            }
1060
0
        }
1061
1062
0
        proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_spare,       tvb, 26, 1, ENC_NA);
1063
0
    }
1064
1065
    // TODO: check CRC
1066
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_crc,           tvb, 26, 4, ENC_BIG_ENDIAN);
1067
1068
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_ssp,           tvb, 28, 4, ENC_BIG_ENDIAN);
1069
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_tail,          tvb, 30, 1, ENC_NA);
1070
0
    proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_pad,           tvb, 31, 1, ENC_NA);
1071
1072
    // handoff the data word of a nominal page
1073
0
    if (even_page_type == 0 && odd_page_type == 0) {
1074
        // create new tvb with the data word
1075
0
        word = wmem_alloc(pinfo->pool, 16);
1076
0
        phtonu16(word + 14, (uint16_t)data_16_1);
1077
0
        phtonu64(word + 6, data_66_17);
1078
0
        phtonu64(word, (((uint64_t) inav_type) << 58) | (data_122_67 << 2) | (data_66_17 >> 48));
1079
1080
0
        next_tvb = tvb_new_child_real_data(tvb, (uint8_t *)word, 16, 16);
1081
0
        add_new_data_source(pinfo, next_tvb, "Galileo I/NAV Word");
1082
1083
        // handoff to appropriate dissector
1084
0
        if (!dissector_try_uint(ubx_gal_inav_word_dissector_table, inav_type, next_tvb, pinfo, tree)) {
1085
0
            call_data_dissector(next_tvb, pinfo, tree);
1086
0
        }
1087
0
    }
1088
1089
0
    return tvb_captured_length(tvb);
1090
0
}
1091
1092
/* Dissect word 0 - I/NAV Spare Word */
1093
0
static int dissect_ubx_gal_inav_word0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1094
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 0 (Spare Word)");
1095
1096
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word0, tvb, 0, 16, ENC_NA);
1097
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word0);
1098
1099
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,   tvb,  0,  1, ENC_NA);
1100
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_time,  tvb,  0,  1, ENC_NA);
1101
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_spare, tvb,  1, 11, ENC_NA);
1102
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_wn,    tvb, 12,  4, ENC_BIG_ENDIAN);
1103
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_tow,   tvb, 12,  4, ENC_BIG_ENDIAN);
1104
1105
0
    return tvb_captured_length(tvb);
1106
0
}
1107
1108
/* Dissect word 1 - Ephemeris (1/4) */
1109
0
static int dissect_ubx_gal_inav_word1(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1110
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 1 (Ephemeris (1/4))");
1111
1112
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word1, tvb, 0, 16, ENC_NA);
1113
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word1);
1114
1115
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,      tvb,  0, 1, ENC_NA);
1116
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_iodnav,   tvb,  0, 2, ENC_BIG_ENDIAN);
1117
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_t0e,      tvb,  2, 2, ENC_BIG_ENDIAN);
1118
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_m0,       tvb,  3, 8, ENC_BIG_ENDIAN);
1119
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_e,        tvb,  7, 8, ENC_BIG_ENDIAN);
1120
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_sqrta,    tvb,  8, 8, ENC_BIG_ENDIAN);
1121
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_reserved, tvb, 15, 1, ENC_NA);
1122
1123
0
    return tvb_captured_length(tvb);
1124
0
}
1125
1126
/* Dissect word 2 - Ephemeris (2/4) */
1127
0
static int dissect_ubx_gal_inav_word2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1128
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 2 (Ephemeris (2/4))");
1129
1130
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word2, tvb, 0, 16, ENC_NA);
1131
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word2);
1132
1133
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,             tvb,  0, 1, ENC_NA);
1134
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_iodnav,          tvb,  0, 2, ENC_BIG_ENDIAN);
1135
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_omega0,          tvb,  2, 4, ENC_BIG_ENDIAN);
1136
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_i0,              tvb,  6, 4, ENC_BIG_ENDIAN);
1137
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_omega,           tvb, 10, 4, ENC_BIG_ENDIAN);
1138
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_incl_angle_rate, tvb, 14, 2, ENC_BIG_ENDIAN);
1139
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_reserved,        tvb, 15, 1, ENC_NA);
1140
1141
0
    return tvb_captured_length(tvb);
1142
0
}
1143
1144
/* Dissect word 3 - Ephemeris (3/4) */
1145
0
static int dissect_ubx_gal_inav_word3(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1146
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 3 (Ephemeris (3/4))");
1147
1148
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word3, tvb, 0, 16, ENC_NA);
1149
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word3);
1150
1151
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,         tvb,  0, 1, ENC_NA);
1152
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_iodnav,      tvb,  0, 2, ENC_BIG_ENDIAN);
1153
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_omega_rate,  tvb,  2, 4, ENC_BIG_ENDIAN);
1154
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_delta_n,     tvb,  5, 2, ENC_BIG_ENDIAN);
1155
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_uc,        tvb,  7, 2, ENC_BIG_ENDIAN);
1156
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_us,        tvb,  9, 2, ENC_BIG_ENDIAN);
1157
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_rc,        tvb, 11, 2, ENC_BIG_ENDIAN);
1158
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_rs,        tvb, 13, 2, ENC_BIG_ENDIAN);
1159
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_sisa_e1_e5b, tvb, 15, 1, ENC_NA);
1160
1161
0
    return tvb_captured_length(tvb);
1162
0
}
1163
1164
/* Dissect word 4 - Ephemeris (4/4) */
1165
0
static int dissect_ubx_gal_inav_word4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1166
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 4 (Ephemeris (4/4))");
1167
1168
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word4, tvb, 0, 16, ENC_NA);
1169
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word4);
1170
1171
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,    tvb,  0, 1, ENC_NA);
1172
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_iodnav, tvb,  0, 2, ENC_BIG_ENDIAN);
1173
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_svid,   tvb,  2, 1, ENC_NA);
1174
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_c_ic,   tvb,  2, 4, ENC_BIG_ENDIAN);
1175
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_c_is,   tvb,  4, 4, ENC_BIG_ENDIAN);
1176
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_t_0c,   tvb,  6, 4, ENC_BIG_ENDIAN);
1177
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f0,   tvb,  8, 8, ENC_BIG_ENDIAN);
1178
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f1,   tvb, 12, 4, ENC_BIG_ENDIAN);
1179
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f2,   tvb, 12, 4, ENC_BIG_ENDIAN);
1180
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_spare,  tvb, 15, 1, ENC_NA);
1181
1182
0
    return tvb_captured_length(tvb);
1183
0
}
1184
1185
/* Dissect word 6 - GST-UTC conversion parameters */
1186
0
static int dissect_ubx_gal_inav_word6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
1187
0
    col_append_str(pinfo->cinfo, COL_INFO, "Word 6 (GST-UTC conversion parameters)");
1188
1189
0
    proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word6, tvb, 0, 16, ENC_NA);
1190
0
    proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word6);
1191
1192
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type,         tvb,  0, 1, ENC_NA);
1193
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_a0,          tvb,  0, 8, ENC_BIG_ENDIAN);
1194
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_a1,          tvb,  4, 4, ENC_BIG_ENDIAN);
1195
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_delta_t_ls,  tvb,  7, 2, ENC_BIG_ENDIAN);
1196
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_t_0t,        tvb,  8, 2, ENC_BIG_ENDIAN);
1197
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_wn_0t,       tvb,  9, 2, ENC_BIG_ENDIAN);
1198
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_wn_lsf,      tvb, 10, 2, ENC_BIG_ENDIAN);
1199
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_dn,          tvb, 11, 2, ENC_BIG_ENDIAN);
1200
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_delta_t_lsf, tvb, 12, 2, ENC_BIG_ENDIAN);
1201
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_tow,         tvb, 12, 4, ENC_BIG_ENDIAN);
1202
0
    proto_tree_add_item(word_tree, hf_ubx_gal_inav_word6_spare,       tvb, 15, 1, ENC_NA);
1203
1204
0
    return tvb_captured_length(tvb);
1205
0
}
1206
1207
15
void proto_register_ubx_gal_inav(void) {
1208
1209
15
    static hf_register_info hf[] = {
1210
15
        {&hf_ubx_gal_inav_even_odd,      {"Even/Odd",      "gal_inav.even_odd",    FT_BOOLEAN, 8,         TFS(&tfs_odd_even),  0x80,                         NULL, HFILL}},
1211
15
        {&hf_ubx_gal_inav_page_type,     {"Page Type",     "gal_inav.page_type",   FT_UINT8,   BASE_DEC,  VALS(GAL_PAGE_TYPE), 0x40,                         NULL, HFILL}},
1212
15
        {&hf_ubx_gal_inav_type,          {"Type",          "gal_inav.type",        FT_UINT8,   BASE_DEC,  NULL,                0x3f,                         NULL, HFILL}},
1213
15
        {&hf_ubx_gal_inav_data_122_67,   {"Data (122-67)", "gal_inav.data_122_67", FT_UINT64,  BASE_HEX,  NULL,                UINT64_C(0x00ffffffffffffff), NULL, HFILL}},
1214
15
        {&hf_ubx_gal_inav_data_66_17,    {"Data (66-17)",  "gal_inav.data_66_17",  FT_UINT64,  BASE_HEX,  NULL,                UINT64_C(0xffffffffffffc000), NULL, HFILL}},
1215
15
        {&hf_ubx_gal_inav_data_16_1,     {"Data (16-1)",   "gal_inav.data_16_1",   FT_UINT64,  BASE_HEX,  NULL,                UINT64_C(0x3fffc00000000000), NULL, HFILL}},
1216
1217
        // OSNMA
1218
15
        {&hf_ubx_gal_inav_osnma_hkroot,        {"HKROOT",                                   "gal_inav.osnma.hkroot",         FT_UINT32,     BASE_HEX,                  NULL,                       0x3fc00000,                   NULL, HFILL}},
1219
15
        {&hf_ubx_gal_inav_osnma_mack,          {"MACK",                                     "gal_inav.osnma.mack",           FT_UINT64,     BASE_HEX,                  NULL,                       UINT64_C(0x003fffffffc00000), NULL, HFILL}},
1220
15
        {&hf_ubx_gal_inav_osnma_nmas,          {"NMA Status (NMAS)",                        "gal_inav.osnma.nmas",           FT_UINT8,      BASE_HEX,                  VALS(GAL_OSNMA_NMAS_CODE),  0xc0,                         NULL, HFILL}},
1221
15
        {&hf_ubx_gal_inav_osnma_cid,           {"Chain ID (CID)",                           "gal_inav.osnma.cid",            FT_UINT8,      BASE_DEC,                  NULL,                       0x30,                         NULL, HFILL}},
1222
15
        {&hf_ubx_gal_inav_osnma_cpks,          {"Chain and Public Key Status (CPKS)",       "gal_inav.osnma.cpks",           FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_CPKS_CODE),  0x0e,                         NULL, HFILL}},
1223
15
        {&hf_ubx_gal_inav_osnma_reserved,      {"Reserved",                                 "gal_inav.osnma.reserved",       FT_UINT8,      BASE_HEX,                  NULL,                       0x01,                         NULL, HFILL}},
1224
15
        {&hf_ubx_gal_inav_osnma_dsm_id,        {"DSM ID",                                   "gal_inav.osnma.dsm_id",         FT_UINT8,      BASE_DEC,                  NULL,                       0xf0,                         NULL, HFILL}},
1225
15
        {&hf_ubx_gal_inav_osnma_dsm_blk_id,    {"DSM Block ID",                             "gal_inav.osnma.dsm_blk_id",     FT_UINT8,      BASE_DEC,                  NULL,                       0x0f,                         NULL, HFILL}},
1226
15
        {&hf_ubx_gal_inav_osnma_dsm_blk,       {"DSM Block",                                "gal_inav.osnma.dsm_blk",        FT_BYTES,      BASE_NONE|SEP_COLON,       NULL,                       0x0,                          NULL, HFILL}},
1227
15
        {&hf_ubx_gal_inav_osnma_tag0,          {"Tag 0",                                    "gal_inav.osnma.tag0",           FT_BYTES,      BASE_NONE|SEP_COLON,       NULL,                       0x0,                          NULL, HFILL}},
1228
15
        {&hf_ubx_gal_inav_osnma_macseq,        {"MACSEQ",                                   "gal_inav.osnma.macseq",         FT_UINT16,     BASE_DEC,                  NULL,                       0xfff0,                       NULL, HFILL}},
1229
15
        {&hf_ubx_gal_inav_osnma_cop,           {"Data Cut-Off Point (COP)",                 "gal_inav.osnma.cop",            FT_UINT8,      BASE_DEC,                  NULL,                       0x0f,                         NULL, HFILL}},
1230
15
        {&hf_ubx_gal_inav_osnma_tag,           {"Tag",                                      "gal_inav.osnma.tag",            FT_BYTES,      BASE_NONE|SEP_COLON,       NULL,                       0x0,                          NULL, HFILL}},
1231
15
        {&hf_ubx_gal_inav_osnma_prn_d,         {"PRN_D",                                    "gal_inav.osnma.prn_d",          FT_UINT8,      BASE_DEC,                  NULL,                       0xff,                         NULL, HFILL}},
1232
15
        {&hf_ubx_gal_inav_osnma_adkd,          {"Authentication Data and Key Delay (ADKD)", "gal_inav.osnma.adkd",           FT_UINT8,      BASE_DEC,                  NULL,                       0xf0,                         NULL, HFILL}},
1233
15
        {&hf_ubx_gal_inav_osnma_key,           {"TESLA Chain Key",                          "gal_inav.osnma.key",            FT_BYTES,      BASE_NONE|SEP_COLON,       NULL,                       0x0,                          NULL, HFILL}},
1234
15
        {&hf_ubx_gal_inav_osnma_padding,       {"MACK Padding",                             "gal_inav.osnma.mack_padding",   FT_BYTES,      BASE_NONE|SEP_COLON,       NULL,                       0x0,                          NULL, HFILL}},
1235
15
        {&hf_ubx_gal_inav_osnma_dsm_nb_dk,     {"Number of DSM-KROOT Blocks (NB_DK)",       "gal_inav.osnma.dsm.nb_dk",      FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_NB_DK_CODE), 0xf0,                         NULL, HFILL}},
1236
15
        {&hf_ubx_gal_inav_osnma_dsm_pkid,      {"Public Key ID (PKID)",                     "gal_inav.osnma.dsm.pkid",       FT_UINT8,      BASE_DEC,                  NULL,                       0x0f,                         NULL, HFILL}},
1237
15
        {&hf_ubx_gal_inav_osnma_dsm_cidkr,     {"KROOT Chain ID (CIDKR)",                   "gal_inav.osnma.dsm.cidkr",      FT_UINT8,      BASE_DEC,                  NULL,                       0xc0,                         NULL, HFILL}},
1238
15
        {&hf_ubx_gal_inav_osnma_dsm_reserved1, {"Reserved 1",                               "gal_inav.osnma.dsm.reserved1",  FT_UINT8,      BASE_HEX,                  NULL,                       0x30,                         NULL, HFILL}},
1239
15
        {&hf_ubx_gal_inav_osnma_dsm_hf,        {"Hash Function (HF)",                       "gal_inav.osnma.dsm.hf",         FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_HF_CODE),    0x0c,                         NULL, HFILL}},
1240
15
        {&hf_ubx_gal_inav_osnma_dsm_mf,        {"MAC Function (MF)",                        "gal_inav.osnma.dsm.mf",         FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_MF_CODE),    0x03,                         NULL, HFILL}},
1241
15
        {&hf_ubx_gal_inav_osnma_dsm_ks,        {"Key Size (KS)",                            "gal_inav.osnma.dsm.ks",         FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_KS_CODE),    0xf0,                         NULL, HFILL}},
1242
15
        {&hf_ubx_gal_inav_osnma_dsm_ts,        {"Tag Size (TS)",                            "gal_inav.osnma.dsm.ts",         FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_TS_CODE),    0x0f,                         NULL, HFILL}},
1243
        // TODO: show the meaning of MACLT entries
1244
15
        {&hf_ubx_gal_inav_osnma_dsm_maclt,     {"MAC Look-up Table (MACLT)",                "gal_inav.osnma.dsm.maclt",      FT_UINT8,      BASE_DEC,                  NULL,                       0x0,                          NULL, HFILL}},
1245
15
        {&hf_ubx_gal_inav_osnma_dsm_reserved2, {"Reserved 2",                               "gal_inav.osnma.dsm.reserved2",  FT_UINT8,      BASE_HEX,                  NULL,                       0xf0,                         NULL, HFILL}},
1246
15
        {&hf_ubx_gal_inav_osnma_dsm_wn_k,      {"KROOT Week Number (WN_K)",                 "gal_inav.osnma.dsm.wn_k",       FT_UINT16,     BASE_DEC,                  NULL,                       0x0fff,                       NULL, HFILL}},
1247
15
        {&hf_ubx_gal_inav_osnma_dsm_towh_k,    {"KROOT Time of Week (TOWH_K)",              "gal_inav.osnma.dsm.towh_k",     FT_UINT8,      BASE_DEC|BASE_UNIT_STRING, UNS(&units_hours),          0xff,                         NULL, HFILL}},
1248
15
        {&hf_ubx_gal_inav_osnma_dsm_alpha,     {"Random Pattern (α)",                       "gal_inav.osnma.dsm.alpha",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1249
15
        {&hf_ubx_gal_inav_osnma_dsm_kroot,     {"KROOT",                                    "gal_inav.osnma.dsm.kroot",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1250
15
        {&hf_ubx_gal_inav_osnma_dsm_ds,        {"Digital Signature (DS)",                   "gal_inav.osnma.dsm.ds",         FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1251
15
        {&hf_ubx_gal_inav_osnma_dsm_p_dk,      {"DSM-KROOT Padding (P_DK)",                 "gal_inav.osnma.dsm.p_dk",       FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1252
15
        {&hf_ubx_gal_inav_osnma_dsm_nb_dp,     {"Number of DSM-PKR Blocks (NB_DP)",         "gal_inav.osnma.dsm.nb_dp",      FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_NB_DP_CODE), 0xf0,                         NULL, HFILL}},
1253
15
        {&hf_ubx_gal_inav_osnma_dsm_mid,       {"Message ID (MID)",                         "gal_inav.osnma.dsm.mid",        FT_UINT8,      BASE_DEC,                  NULL,                       0x0f,                         NULL, HFILL}},
1254
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_0,     {"x_0_0",                                    "gal_inav.osnma.dsm.x_0_0",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1255
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_1,     {"x_0_1",                                    "gal_inav.osnma.dsm.x_0_1",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1256
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_2,     {"x_0_2",                                    "gal_inav.osnma.dsm.x_0_2",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1257
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_3,     {"x_0_3",                                    "gal_inav.osnma.dsm.x_0_3",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1258
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_4,     {"x_0_4",                                    "gal_inav.osnma.dsm.x_0_4",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1259
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_5,     {"x_0_5",                                    "gal_inav.osnma.dsm.x_0_5",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1260
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_6,     {"x_0_6",                                    "gal_inav.osnma.dsm.x_0_6",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1261
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_7,     {"x_0_7",                                    "gal_inav.osnma.dsm.x_0_7",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1262
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_8,     {"x_0_8",                                    "gal_inav.osnma.dsm.x_0_8",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1263
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_9,     {"x_0_9",                                    "gal_inav.osnma.dsm.x_0_9",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1264
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_10,    {"x_0_10",                                   "gal_inav.osnma.dsm.x_0_10",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1265
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_11,    {"x_0_11",                                   "gal_inav.osnma.dsm.x_0_11",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1266
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_12,    {"x_0_12",                                   "gal_inav.osnma.dsm.x_0_12",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1267
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_13,    {"x_0_13",                                   "gal_inav.osnma.dsm.x_0_13",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1268
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_14,    {"x_0_14",                                   "gal_inav.osnma.dsm.x_0_14",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1269
15
        {&hf_ubx_gal_inav_osnma_dsm_x_0_15,    {"x_0_15",                                   "gal_inav.osnma.dsm.x_0_15",     FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1270
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_0,     {"x_1_0",                                    "gal_inav.osnma.dsm.x_1_0",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1271
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_1,     {"x_1_1",                                    "gal_inav.osnma.dsm.x_1_1",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1272
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_2,     {"x_1_2",                                    "gal_inav.osnma.dsm.x_1_2",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1273
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_3,     {"x_1_3",                                    "gal_inav.osnma.dsm.x_1_3",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1274
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_4,     {"x_1_4",                                    "gal_inav.osnma.dsm.x_1_4",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1275
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_5,     {"x_1_5",                                    "gal_inav.osnma.dsm.x_1_5",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1276
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_6,     {"x_1_6",                                    "gal_inav.osnma.dsm.x_1_6",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1277
15
        {&hf_ubx_gal_inav_osnma_dsm_x_1_7,     {"x_1_7",                                    "gal_inav.osnma.dsm.x_1_7",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1278
15
        {&hf_ubx_gal_inav_osnma_dsm_x_2_0,     {"x_2_0",                                    "gal_inav.osnma.dsm.x_2_0",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1279
15
        {&hf_ubx_gal_inav_osnma_dsm_x_2_1,     {"x_2_1",                                    "gal_inav.osnma.dsm.x_2_1",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1280
15
        {&hf_ubx_gal_inav_osnma_dsm_x_2_2,     {"x_2_2",                                    "gal_inav.osnma.dsm.x_2_2",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1281
15
        {&hf_ubx_gal_inav_osnma_dsm_x_2_3,     {"x_2_3",                                    "gal_inav.osnma.dsm.x_2_3",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1282
15
        {&hf_ubx_gal_inav_osnma_dsm_x_3_0,     {"x_3_0",                                    "gal_inav.osnma.dsm.x_3_0",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1283
15
        {&hf_ubx_gal_inav_osnma_dsm_x_3_1,     {"x_3_1",                                    "gal_inav.osnma.dsm.x_3_1",      FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1284
15
        {&hf_ubx_gal_inav_osnma_dsm_npkt,      {"New Public Key Type (NPKT)",               "gal_inav.osnma.dsm.npkt",       FT_UINT8,      BASE_DEC,                  VALS(GAL_OSNMA_NPKT_CODE),  0xf0,                         NULL, HFILL}},
1285
15
        {&hf_ubx_gal_inav_osnma_dsm_npkid,     {"New Public Key ID (NPKID)",                "gal_inav.osnma.dsm.npkid",      FT_UINT8,      BASE_DEC,                  NULL,                       0x0f,                         NULL, HFILL}},
1286
15
        {&hf_ubx_gal_inav_osnma_dsm_npk,       {"New Public Key (NPK)",                     "gal_inav.osnma.dsm.npk",        FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1287
15
        {&hf_ubx_gal_inav_osnma_dsm_p_dp,      {"DSM-PKR Padding (P_DP)",                   "gal_inav.osnma.dsm.p_dp",       FT_BYTES,      BASE_NONE,                 NULL,                       0x0,                          NULL, HFILL}},
1288
1289
        // SAR
1290
15
        {&hf_ubx_gal_inav_sar_start_bit, {"Start bit",                          "gal_inav.sar.start_bit", FT_BOOLEAN, 32,        NULL,                             0x20000000,         NULL,     HFILL}},
1291
15
        {&hf_ubx_gal_inav_sar_long_rlm,  {"Long RLM",                           "gal_inav.sar.long_rlm",  FT_BOOLEAN, 32,        NULL,                             0x10000000,         NULL,     HFILL}},
1292
15
        {&hf_ubx_gal_inav_sar_rlm_data,  {"RLM data",                           "gal_inav.sar.rlm_data",  FT_UINT32,  BASE_HEX,  NULL,                             0x0fffff00,         NULL,     HFILL}},
1293
15
        {&hf_ubx_gal_inav_sar_beacon_id, {"Beacon ID",                          "gal_inav.sar.beacon_id", FT_UINT64,  BASE_HEX,  NULL,                             UINT64_C(0xfffffffffffffff0), NULL, HFILL}},
1294
15
        {&hf_ubx_gal_inav_sar_msg_code,  {"Message code",                       "gal_inav.sar.msg_code",  FT_UINT32,  BASE_HEX,  VALS(GAL_SAR_SHORT_RLM_MSG_CODE), 0x000f0000,         NULL,     HFILL}},
1295
1296
15
        {&hf_ubx_gal_inav_spare,      {"Spare",      "gal_inav.spare",      FT_UINT8,  BASE_HEX,  NULL,          0xc0,       NULL, HFILL}},
1297
15
        {&hf_ubx_gal_inav_reserved_1, {"Reserved 1", "gal_inav.reserved_1", FT_NONE,   BASE_NONE, NULL,          0x0,        NULL, HFILL}},
1298
15
        {&hf_ubx_gal_inav_crc,        {"CRC",        "gal_inav.crc",        FT_UINT32, BASE_HEX,  NULL,          0x3fffffc0, NULL, HFILL}},
1299
15
        {&hf_ubx_gal_inav_ssp,        {"SSP",        "gal_inav.ssp",        FT_UINT32, BASE_HEX,  VALS(GAL_SSP), 0x003fc000, NULL, HFILL}},
1300
15
        {&hf_ubx_gal_inav_tail,       {"Tail",       "gal_inav.tail",       FT_UINT8,  BASE_HEX,  NULL,          0x3f,       NULL, HFILL}},
1301
15
        {&hf_ubx_gal_inav_pad,        {"Pad",        "gal_inav.pad",        FT_UINT8,  BASE_HEX,  NULL,          0x0,        NULL, HFILL}},
1302
1303
        // Data words
1304
15
        {&hf_ubx_gal_inav_word_type,     {"Type",                "gal_inav.word.type",     FT_UINT8,      BASE_DEC,  NULL, 0xfc, NULL, HFILL}},
1305
1306
        // Word 0
1307
15
        {&hf_ubx_gal_inav_word0,         {"Word 0 (Spare Word)", "gal_inav.word0",         FT_NONE,       BASE_NONE, NULL, 0x0,  NULL, HFILL}},
1308
15
        {&hf_ubx_gal_inav_word0_time,    {"Time",                "gal_inav.word0.time",    FT_UINT8,      BASE_HEX,  NULL, 0x03, NULL, HFILL}},
1309
15
        {&hf_ubx_gal_inav_word0_spare,   {"Spare",               "gal_inav.word0.spare",   FT_BYTES,      BASE_NONE|SEP_SPACE, NULL, 0x0,  NULL, HFILL}},
1310
15
        {&hf_ubx_gal_inav_word0_wn,      {"Week Number",         "gal_inav.word0.wn",      FT_UINT32,     BASE_DEC,  NULL, 0xfff00000,  NULL, HFILL}},
1311
15
        {&hf_ubx_gal_inav_word0_tow,     {"Time of Week",        "gal_inav.word0.tow",     FT_UINT32,     BASE_DEC,  NULL, 0x000fffff,  NULL, HFILL}},
1312
1313
        // Word 1
1314
15
        {&hf_ubx_gal_inav_word1,         {"Word 1 (Ephemeris (1/4))",                                   "gal_inav.word1",          FT_NONE,   BASE_NONE,   NULL,                       0x0,                          NULL, HFILL}},
1315
15
        {&hf_ubx_gal_inav_word1_iodnav,  {"IOD_nav",                                                    "gal_inav.word1.iod_nav",  FT_UINT16, BASE_DEC,    NULL,                       0x03ff,                       NULL, HFILL}},
1316
15
        {&hf_ubx_gal_inav_word1_t0e,     {"Ephemeris reference time (t_0e)",                            "gal_inav.word1.t_0e",     FT_UINT16, BASE_CUSTOM, CF_FUNC(&fmt_t0e),          0xfffc,                       NULL, HFILL}},
1317
15
        {&hf_ubx_gal_inav_word1_m0,      {"Mean anomaly at reference time (M" UTF8_SUBSCRIPT_ZERO ")",  "gal_inav.word1.m_0",      FT_INT64,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles), UINT64_C(0x03fffffffc000000), NULL, HFILL}},
1318
15
        {&hf_ubx_gal_inav_word1_e,       {"Eccentricity (e)",                                           "gal_inav.word1.e",        FT_UINT64, BASE_CUSTOM, CF_FUNC(&fmt_e),            UINT64_C(0x03fffffffc000000), NULL, HFILL}},
1319
15
        {&hf_ubx_gal_inav_word1_sqrta,   {"Square root of the semi-major axis (" UTF8_SQUARE_ROOT "a)", "gal_inav.word1.sqrt_a",   FT_UINT64, BASE_CUSTOM, CF_FUNC(&fmt_sqrt_a),       UINT64_C(0x00000003fffffffc), NULL, HFILL}},
1320
15
        {&hf_ubx_gal_inav_word1_reserved,{"Reserved",                                                   "gal_inav.word1.reserved", FT_UINT8,  BASE_HEX,    NULL,                       0x03,                         NULL, HFILL}},
1321
1322
        // Word 2
1323
15
        {&hf_ubx_gal_inav_word2,                 {"Word 2 (Ephemeris (2/4))",                                                                                  "gal_inav.word2",          FT_NONE,   BASE_NONE,   NULL,                            0x0,        NULL, HFILL}},
1324
15
        {&hf_ubx_gal_inav_word2_iodnav,          {"IOD_nav",                                                                                                   "gal_inav.word2.iod_nav",  FT_UINT16, BASE_DEC,    NULL,                            0x03ff,     NULL, HFILL}},
1325
15
        {&hf_ubx_gal_inav_word2_omega0,          {"Longitude of ascending node of orbital plane at weekly epoch (" UTF8_CAPITAL_OMEGA UTF8_SUBSCRIPT_ZERO ")", "gal_inav.word2.omega_0",  FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles),      0xffffffff, NULL, HFILL}},
1326
15
        {&hf_ubx_gal_inav_word2_i0,              {"Inclination angle at reference time (i" UTF8_SUBSCRIPT_ZERO ")",                                            "gal_inav.word2.i_0",      FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles),      0xffffffff, NULL, HFILL}},
1327
15
        {&hf_ubx_gal_inav_word2_omega,           {"Argument of perigee (" UTF8_OMEGA ")",                                                                      "gal_inav.word2.omega",    FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles),      0xffffffff, NULL, HFILL}},
1328
15
        {&hf_ubx_gal_inav_word2_incl_angle_rate, {"Rate of change of inclination angle (di)",                                                                  "gal_inav.word2.di",       FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles_rate), 0xfffc,     NULL, HFILL}},
1329
15
        {&hf_ubx_gal_inav_word2_reserved,        {"Reserved",                                                                                                  "gal_inav.word2.reserved", FT_UINT8,  BASE_HEX,    NULL,                            0x03,       NULL, HFILL}},
1330
1331
        // Word 3
1332
15
        {&hf_ubx_gal_inav_word3,             {"Word 3 (Ephemeris (3/4))",                                                            "gal_inav.word3",             FT_NONE,   BASE_NONE,   NULL,                            0x0,        NULL, HFILL}},
1333
15
        {&hf_ubx_gal_inav_word3_iodnav,      {"IOD_nav",                                                                             "gal_inav.word3.iod_nav",     FT_UINT16, BASE_DEC,    NULL,                            0x03ff,     NULL, HFILL}},
1334
15
        {&hf_ubx_gal_inav_word3_omega_rate,  {"Rate of change of right ascension (dot " UTF8_CAPITAL_OMEGA ")",                      "gal_inav.word3.omega_rate",  FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles_rate), 0xffffff00, NULL, HFILL}},
1335
15
        {&hf_ubx_gal_inav_word3_delta_n,     {"Mean motion difference from computed value (" UTF8_CAPITAL_DELTA "n)",                "gal_inav.word3.delta_n",     FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_semi_circles_rate), 0xffff,     NULL, HFILL}},
1336
15
        {&hf_ubx_gal_inav_word3_c_uc,        {"Amplitude of the cosine harmonic correction term to the argument of latitude (C_UC)", "gal_inav.word3.c_uc",        FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_lat_correction),    0xffff,     NULL, HFILL}},
1337
15
        {&hf_ubx_gal_inav_word3_c_us,        {"Amplitude of the sine harmonic correction term to the argument of latitude (C_US)",   "gal_inav.word3.c_us",        FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_lat_correction),    0xffff,     NULL, HFILL}},
1338
15
        {&hf_ubx_gal_inav_word3_c_rc,        {"Amplitude of the cosine harmonic correction term to the orbit radius (C_RC)",         "gal_inav.word3.c_rc",        FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_orbit_correction),  0xffff,     NULL, HFILL}},
1339
15
        {&hf_ubx_gal_inav_word3_c_rs,        {"Amplitude of the sine harmonic correction term to the orbit radius (C_RS)",           "gal_inav.word3.c_rs",        FT_INT16,  BASE_CUSTOM, CF_FUNC(&fmt_orbit_correction),  0xffff,     NULL, HFILL}},
1340
15
        {&hf_ubx_gal_inav_word3_sisa_e1_e5b, {"Signal-in-Space Accuracy (SISA(E1,E5b))",                                             "gal_inav.word3.sisa_e1_e5b", FT_UINT8,  BASE_CUSTOM, CF_FUNC(&fmt_sisa),              0xff,       NULL, HFILL}},
1341
1342
        // Word 4
1343
15
        {&hf_ubx_gal_inav_word4,             {"Word 4 (Ephemeris (4/4))",                                                            "gal_inav.word4",             FT_NONE,   BASE_NONE,   NULL,                            0x0,        NULL, HFILL}},
1344
15
        {&hf_ubx_gal_inav_word4_iodnav,      {"IOD_nav",                                                                             "gal_inav.word4.iod_nav",     FT_UINT16, BASE_DEC,    NULL,                            0x03ff,     NULL, HFILL}},
1345
15
        {&hf_ubx_gal_inav_word4_svid,        {"SVID",                                                                                "gal_inav.word4.svid",        FT_UINT8,  BASE_DEC,    NULL,                            0xfc,       NULL, HFILL}},
1346
15
        {&hf_ubx_gal_inav_word4_c_ic,        {"Amplitude of the cosine harmonic correction term to the angle of inclination (C_IC)", "gal_inav.word4.c_ic",        FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_lat_correction),    0x03fffc00, NULL, HFILL}},
1347
15
        {&hf_ubx_gal_inav_word4_c_is,        {"Amplitude of the sine harmonic correction term to the angle of inclination (C_IS)",   "gal_inav.word4.c_is",        FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_lat_correction),    0x03fffc00, NULL, HFILL}},
1348
15
        {&hf_ubx_gal_inav_word4_t_0c,        {"Clock correction data reference Time of Week (t_0c)",                                 "gal_inav.word4.t_0c",        FT_UINT32, BASE_CUSTOM, CF_FUNC(&fmt_clk_correction),    0x03fff000, NULL, HFILL}},
1349
15
        {&hf_ubx_gal_inav_word4_a_f0,        {"SV clock bias correction coefficient (a_f0)",                                         "gal_inav.word4.a_f0",        FT_INT64,  BASE_CUSTOM, CF_FUNC(&fmt_sv_clk_bias),       0x0fffffffe0000000, NULL, HFILL}},
1350
15
        {&hf_ubx_gal_inav_word4_a_f1,        {"SV clock drift correction coefficient (a_f1)",                                        "gal_inav.word4.a_f1",        FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_sv_clk_drift),      0x1fffff00, NULL, HFILL}},
1351
15
        {&hf_ubx_gal_inav_word4_a_f2,        {"SV clock drift rate correction coefficient (a_f2)",                                   "gal_inav.word4.a_f2",        FT_INT32,  BASE_CUSTOM, CF_FUNC(&fmt_sv_clk_drift_rate), 0x000000fc, NULL, HFILL}},
1352
15
        {&hf_ubx_gal_inav_word4_spare,       {"Spare",                                                                               "gal_inav.word4.spare",       FT_UINT8,  BASE_HEX,    NULL,                            0x03,       NULL, HFILL}},
1353
1354
        // Word 6
1355
15
        {&hf_ubx_gal_inav_word6,             {"Word 6 (GST-UTC conversion parameters)",                                         "gal_inav.word6",             FT_NONE,   BASE_NONE,                 NULL,                       0x0,                NULL, HFILL}},
1356
15
        {&hf_ubx_gal_inav_word6_a0,          {"Constant term of polynomial (A_0)",                                              "gal_inav.word6.a_0",         FT_INT64,  BASE_CUSTOM,               CF_FUNC(&fmt_a0),           0x03fffffffc000000, NULL, HFILL}},
1357
15
        {&hf_ubx_gal_inav_word6_a1,          {"1st order term of polynomial (A_1)",                                             "gal_inav.word6.a_1",         FT_INT32,  BASE_CUSTOM,               CF_FUNC(&fmt_a1),           0x03fffffc,         NULL, HFILL}},
1358
15
        {&hf_ubx_gal_inav_word6_delta_t_ls,  {"Leap Second count before leap second adjustment (" UTF8_CAPITAL_DELTA "t_LS)",   "gal_inav.word6.delta_t_ls",  FT_INT16,  BASE_DEC|BASE_UNIT_STRING, UNS(&units_second_seconds), 0x03fc,             NULL, HFILL}},
1359
15
        {&hf_ubx_gal_inav_word6_t_0t,        {"UTC data reference Time of Week (t_0t)",                                         "gal_inav.word6.t_0t",        FT_UINT16, BASE_CUSTOM,               CF_FUNC(&fmt_t_0t),         0x03fc,             NULL, HFILL}},
1360
15
        {&hf_ubx_gal_inav_word6_wn_0t,       {"UTC data reference Week Number (WN_0t)",                                         "gal_inav.word6.wn_0t",       FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_week_weeks),     0x03fc,             NULL, HFILL}},
1361
15
        {&hf_ubx_gal_inav_word6_wn_lsf,      {"Week Number of leap second adjustment (WN_LSF)",                                 "gal_inav.word6.wn_lsf",      FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_week_weeks),     0x03fc,             NULL, HFILL}},
1362
15
        {&hf_ubx_gal_inav_word6_dn,          {"Day Number at the end of which a leap second adjustment becomes effective (DN)", "gal_inav.word6.dn",          FT_UINT16, BASE_DEC, VALS(DAY_NUMBER),                            0x0380,             NULL, HFILL}},
1363
15
        {&hf_ubx_gal_inav_word6_delta_t_lsf, {"Leap Second count after leap second adjustment (" UTF8_CAPITAL_DELTA "t_LSF)",   "gal_inav.word6.delta_t_lsf", FT_INT16,  BASE_DEC|BASE_UNIT_STRING, UNS(&units_second_seconds), 0x7f80,             NULL, HFILL}},
1364
15
        {&hf_ubx_gal_inav_word6_tow,         {"Time of Week (TOW)",                                                             "gal_inav.word6.tow",         FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_second_seconds), 0x007ffff8,         NULL, HFILL}},
1365
15
        {&hf_ubx_gal_inav_word6_spare,       {"Spare",                                                                          "gal_inav.word6.spare",       FT_UINT8,  BASE_HEX,                  NULL,                       0x07,               NULL, HFILL}},
1366
15
    };
1367
1368
15
    static int *ett[] = {
1369
15
        &ett_ubx_gal_inav,
1370
15
        &ett_ubx_gal_inav_word0,
1371
15
        &ett_ubx_gal_inav_word1,
1372
15
        &ett_ubx_gal_inav_word2,
1373
15
        &ett_ubx_gal_inav_word3,
1374
15
        &ett_ubx_gal_inav_word4,
1375
15
        &ett_ubx_gal_inav_word6,
1376
15
        &ett_ubx_gal_inav_osnma,
1377
15
        &ett_ubx_gal_inav_osnma_hkroot_msg,
1378
15
        &ett_ubx_gal_inav_osnma_mack_msg,
1379
15
        &ett_ubx_gal_inav_osnma_mack_tag[0],
1380
15
        &ett_ubx_gal_inav_osnma_mack_tag[1],
1381
15
        &ett_ubx_gal_inav_osnma_mack_tag[2],
1382
15
        &ett_ubx_gal_inav_osnma_mack_tag[3],
1383
15
        &ett_ubx_gal_inav_osnma_mack_tag[4],
1384
15
        &ett_ubx_gal_inav_osnma_mack_tag[5],
1385
15
        &ett_ubx_gal_inav_osnma_mack_tag[6],
1386
15
        &ett_ubx_gal_inav_osnma_mack_tag[7],
1387
15
        &ett_ubx_gal_inav_osnma_mack_tag[8],
1388
15
        &ett_ubx_gal_inav_osnma_dsm,
1389
15
        &ett_ubx_gal_inav_sar,
1390
15
        &ett_ubx_gal_inav_sar_rlm,
1391
15
    };
1392
1393
15
    proto_ubx_gal_inav = proto_register_protocol("Galileo E1-B I/NAV Navigation Message", "Galileo I/NAV", "gal_inav");
1394
1395
15
    proto_register_field_array(proto_ubx_gal_inav, hf, array_length(hf));
1396
15
    proto_register_subtree_array(ett, array_length(ett));
1397
1398
15
    register_dissector("ubx_gal_inav", dissect_ubx_gal_inav, proto_ubx_gal_inav);
1399
1400
15
    ubx_gal_inav_word_dissector_table = register_dissector_table("ubx.rxm.sfrbx.gal_inav.word",
1401
15
            "Galileo I/NAV Word", proto_ubx_gal_inav, FT_UINT8, BASE_DEC);
1402
15
}
1403
1404
15
void proto_reg_handoff_ubx_gal_inav(void) {
1405
15
    dissector_add_uint("ubx.rxm.sfrbx.gnssid", GNSS_ID_GALILEO, create_dissector_handle(dissect_ubx_gal_inav, proto_ubx_gal_inav));
1406
1407
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 0, create_dissector_handle(dissect_ubx_gal_inav_word0, proto_ubx_gal_inav));
1408
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 1, create_dissector_handle(dissect_ubx_gal_inav_word1, proto_ubx_gal_inav));
1409
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 2, create_dissector_handle(dissect_ubx_gal_inav_word2, proto_ubx_gal_inav));
1410
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 3, create_dissector_handle(dissect_ubx_gal_inav_word3, proto_ubx_gal_inav));
1411
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 4, create_dissector_handle(dissect_ubx_gal_inav_word4, proto_ubx_gal_inav));
1412
15
    dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 6, create_dissector_handle(dissect_ubx_gal_inav_word6, proto_ubx_gal_inav));
1413
15
}