Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ubx-galileo_e1b_inav.c
blobae21509e0f503788b19bc57a745cbd142a12152d
1 /* packet-ubx-galileo_e1b_inav.c
2 * Dissection of Galileo E1-B I/NAV navigation messages
3 * (as provided by UBX-RXM-SFRBX).
5 * By Timo Warns <timo.warns@gmail.com>
6 * Copyright 2023 Timo Warns
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@unicom.net>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/tfs.h>
19 #include <wsutil/array.h>
20 #include <wsutil/pint.h>
21 #include <wsutil/utf8_entities.h>
23 #include "packet-ubx.h"
26 * Dissects Galileo E1-B I/NAV navigation messages
27 * as encoded by UBX (in UBX-RXM-SFRBX messages).
28 * Based on Galileo OS SIS ICD Issue 2.1
31 // Initialize the protocol and registered fields
32 static int proto_ubx_gal_inav;
34 static int hf_ubx_gal_inav_even_odd;
35 static int hf_ubx_gal_inav_page_type;
36 static int hf_ubx_gal_inav_type;
37 static int hf_ubx_gal_inav_data_122_67;
38 static int hf_ubx_gal_inav_data_66_17;
39 static int hf_ubx_gal_inav_data_16_1;
40 static int hf_ubx_gal_inav_osnma;
41 static int hf_ubx_gal_inav_sar_start_bit;
42 static int hf_ubx_gal_inav_sar_long_rlm;
43 static int hf_ubx_gal_inav_sar_beacon_1;
44 static int hf_ubx_gal_inav_sar_rlm_data;
45 static int hf_ubx_gal_inav_spare;
46 static int hf_ubx_gal_inav_ssp;
47 static int hf_ubx_gal_inav_crc;
48 static int hf_ubx_gal_inav_tail;
49 static int hf_ubx_gal_inav_pad;
50 static int hf_ubx_gal_inav_reserved_1;
52 static int hf_ubx_gal_inav_word_type;
54 static int hf_ubx_gal_inav_word0;
55 static int hf_ubx_gal_inav_word0_time;
56 static int hf_ubx_gal_inav_word0_spare;
57 static int hf_ubx_gal_inav_word0_wn;
58 static int hf_ubx_gal_inav_word0_tow;
60 static int hf_ubx_gal_inav_word1;
61 static int hf_ubx_gal_inav_word1_iodnav;
62 static int hf_ubx_gal_inav_word1_t0e;
63 static int hf_ubx_gal_inav_word1_m0;
64 static int hf_ubx_gal_inav_word1_e;
65 static int hf_ubx_gal_inav_word1_sqrta;
66 static int hf_ubx_gal_inav_word1_reserved;
68 static int hf_ubx_gal_inav_word2;
69 static int hf_ubx_gal_inav_word2_iodnav;
70 static int hf_ubx_gal_inav_word2_omega0;
71 static int hf_ubx_gal_inav_word2_i0;
72 static int hf_ubx_gal_inav_word2_omega;
73 static int hf_ubx_gal_inav_word2_incl_angle_rate;
74 static int hf_ubx_gal_inav_word2_reserved;
76 static int hf_ubx_gal_inav_word3;
77 static int hf_ubx_gal_inav_word3_iodnav;
78 static int hf_ubx_gal_inav_word3_omega_rate;
79 static int hf_ubx_gal_inav_word3_delta_n;
80 static int hf_ubx_gal_inav_word3_c_uc;
81 static int hf_ubx_gal_inav_word3_c_us;
82 static int hf_ubx_gal_inav_word3_c_rc;
83 static int hf_ubx_gal_inav_word3_c_rs;
84 static int hf_ubx_gal_inav_word3_sisa_e1_e5b;
86 static int hf_ubx_gal_inav_word4;
87 static int hf_ubx_gal_inav_word4_iodnav;
88 static int hf_ubx_gal_inav_word4_svid;
89 static int hf_ubx_gal_inav_word4_c_ic;
90 static int hf_ubx_gal_inav_word4_c_is;
91 static int hf_ubx_gal_inav_word4_t_0c;
92 static int hf_ubx_gal_inav_word4_a_f0;
93 static int hf_ubx_gal_inav_word4_a_f1;
94 static int hf_ubx_gal_inav_word4_a_f2;
95 static int hf_ubx_gal_inav_word4_spare;
97 static dissector_table_t ubx_gal_inav_word_dissector_table;
99 static int ett_ubx_gal_inav;
100 static int ett_ubx_gal_inav_word0;
101 static int ett_ubx_gal_inav_word1;
102 static int ett_ubx_gal_inav_word2;
103 static int ett_ubx_gal_inav_word3;
104 static int ett_ubx_gal_inav_word4;
105 static int ett_ubx_gal_inav_sar;
107 static const value_string GAL_PAGE_TYPE[] = {
108 {0, "nominal"},
109 {1, "alert"},
110 {0, NULL},
113 static const value_string GAL_SSP[] = {
114 {0x04, "SSP 1"},
115 {0x2b, "SSP 2"},
116 {0x2f, "SSP 3"},
117 {0, NULL},
120 /* Format clock correction (with scale factor 60) for
121 * t_0c
123 static void fmt_clk_correction(char *label, uint32_t c) {
124 snprintf(label, ITEM_LABEL_LENGTH, "%u s", 60 * c);
127 /* Format radians (with 2^-29 scale factor) for
128 * amplitude of harmonic correction terms
130 static void fmt_lat_correction(char *label, int16_t c) {
131 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-29 radians", c);
134 /* Format meters (with 2^-5 scale factor) for
135 * amplitude of orbit correction terms
137 static void fmt_orbit_correction(char *label, int16_t c) {
138 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-5 m", c);
141 /* Format semi-circles (with 2^-31 scale factor) for
142 * - mean anomaly at reference time
143 * - longitude of ascending node of orbital plane at weekly epoch
144 * - inclination angle at reference time
145 * - argument of perigee
147 static void fmt_semi_circles(char *label, int32_t c) {
148 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-31 semi-circles", c);
151 /* Format rate of semi-circles (with 2^-43 scale factor) for
152 * - inclination angle
153 * - right ascension
154 * - mean motion difference
156 static void fmt_semi_circles_rate(char *label, int16_t c) {
157 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-43 semi-circles/s", c);
160 /* Format SISA */
161 static void fmt_sisa(char *label, uint8_t i) {
162 if (i <= 49) {
163 // 0 cm to 49 cm with 1 cm resolution
164 snprintf(label, ITEM_LABEL_LENGTH, "%u cm", i);
166 else if (i <= 74) {
167 // 50 cm to 98 cm with 2 cm resolution
168 snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 50 + ((i - 50) * 2));
170 else if (i <= 99) {
171 // 100 cm to 196 cm with 4 cm resolution
172 snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 100 + ((i - 75) * 4));
174 else if (i <= 125) {
175 // 200 cm to 600 cm with 16 cm resolution
176 snprintf(label, ITEM_LABEL_LENGTH, "%u cm", 200 + ((i - 100) * 16));
178 else if (i <= 254) {
179 // Spare
180 snprintf(label, ITEM_LABEL_LENGTH, "Spare");
182 else { // i == 255
183 snprintf(label, ITEM_LABEL_LENGTH, "No Accuracy Prediction Available (NAPA)");
187 /* Format SV clock bias (with 2^-34 scale factor) for
188 * a_f0
190 static void fmt_sv_clk_bias(char *label, int32_t c) {
191 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-34 s", c);
194 /* Format SV clock drift (with 2^-46 scale factor) for
195 * a_f1
197 static void fmt_sv_clk_drift(char *label, int32_t c) {
198 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-46 s/s", c);
201 /* Format SV clock drift rate (with 2^-59 scale factor) for
202 * a_f1
204 static void fmt_sv_clk_drift_rate(char *label, int32_t c) {
205 snprintf(label, ITEM_LABEL_LENGTH, "%d * 2^-59 s/s" UTF8_SUPERSCRIPT_TWO, c);
208 /* Format eccentricity */
209 static void fmt_e(char *label, uint64_t c) {
210 snprintf(label, ITEM_LABEL_LENGTH, "%" PRIu64 " * 2^-33", c);
213 /* Format square root of the semi-major axis */
214 static void fmt_sqrt_a(char *label, uint64_t c) {
215 snprintf(label, ITEM_LABEL_LENGTH, "%" PRIu64 " * 2^-19 " UTF8_SQUARE_ROOT "m", c);
218 /* Format ephemeris reference time */
219 static void fmt_t0e(char *label, uint32_t c) {
220 c = c * 60;
221 snprintf(label, ITEM_LABEL_LENGTH, "%ds", c);
224 /* Dissect Galileo E1-B I/NAV navigation message */
225 static int dissect_ubx_gal_inav(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
226 tvbuff_t *next_tvb;
228 bool sar_start, sar_long_rlm;
229 uint32_t inav_type = 0, even_page_type, odd_page_type;
230 uint64_t data_122_67 = 0, data_66_17 = 0, data_16_1 = 0;
231 uint8_t *word;
233 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Galileo E1-B I/NAV");
234 col_clear(pinfo->cinfo, COL_INFO);
236 proto_tree *gal_inav_tree = proto_tree_add_subtree(tree, tvb, 0, 32, ett_ubx_gal_inav, NULL, "Galileo E1-B I/NAV");
238 // even page
239 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_even_odd, tvb, 0, 1, ENC_NA);
240 proto_tree_add_item_ret_uint(gal_inav_tree, hf_ubx_gal_inav_page_type, tvb, 0, 1, ENC_NA, &even_page_type);
242 if (even_page_type == 1) { // alert page
243 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_reserved_1, tvb, 0, 15, ENC_NA);
245 else if (even_page_type == 0) { // nominal page
246 proto_tree_add_item_ret_uint(gal_inav_tree, hf_ubx_gal_inav_type, tvb, 0, 1, ENC_NA, &inav_type);
247 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);
248 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);
251 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_tail, tvb, 14, 1, ENC_NA);
252 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_pad, tvb, 15, 1, ENC_NA);
255 // odd page
256 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_even_odd, tvb, 16, 1, ENC_NA);
257 proto_tree_add_item_ret_uint(gal_inav_tree, hf_ubx_gal_inav_page_type, tvb, 16, 1, ENC_NA, &odd_page_type);
259 if (odd_page_type == 1) { // alert page
260 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_reserved_1, tvb, 16, 11, ENC_NA);
262 else if (odd_page_type == 0) { // nominal page
263 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);
264 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_osnma, tvb, 16, 8, ENC_BIG_ENDIAN);
266 proto_tree *sar_tree = proto_tree_add_subtree(gal_inav_tree, tvb, 23, 4, ett_ubx_gal_inav_sar, NULL, "SAR");
267 proto_tree_add_item_ret_boolean(sar_tree, hf_ubx_gal_inav_sar_start_bit, tvb, 23, 4, ENC_BIG_ENDIAN, &sar_start);
268 proto_tree_add_item_ret_boolean(sar_tree, hf_ubx_gal_inav_sar_long_rlm, tvb, 23, 4, ENC_BIG_ENDIAN, &sar_long_rlm);
269 if (sar_start) {
270 proto_tree_add_item(sar_tree, hf_ubx_gal_inav_sar_beacon_1, tvb, 23, 4, ENC_BIG_ENDIAN);
272 else {
273 // TODO: add more elaborate dissection for subsequent RLM data (requiring state tracking)
274 proto_tree_add_item(sar_tree, hf_ubx_gal_inav_sar_rlm_data, tvb, 23, 4, ENC_BIG_ENDIAN);
277 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_spare, tvb, 26, 1, ENC_NA);
280 // TODO: check CRC
281 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_crc, tvb, 26, 4, ENC_BIG_ENDIAN);
283 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_ssp, tvb, 28, 4, ENC_BIG_ENDIAN);
284 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_tail, tvb, 30, 1, ENC_NA);
285 proto_tree_add_item(gal_inav_tree, hf_ubx_gal_inav_pad, tvb, 31, 1, ENC_NA);
287 // handoff the data word of a nominal page
288 if (even_page_type == 0 && odd_page_type == 0) {
289 // create new tvb with the data word
290 word = wmem_alloc(pinfo->pool, 16);
291 phton16(word + 14, (uint16_t)data_16_1);
292 phton64(word + 6, data_66_17);
293 phton64(word, (((uint64_t) inav_type) << 58) | (data_122_67 << 2) | (data_66_17 >> 48));
295 next_tvb = tvb_new_child_real_data(tvb, (uint8_t *)word, 16, 16);
296 add_new_data_source(pinfo, next_tvb, "Galileo I/NAV Word");
298 // handoff to appropriate dissector
299 if (!dissector_try_uint(ubx_gal_inav_word_dissector_table, inav_type, next_tvb, pinfo, tree)) {
300 call_data_dissector(next_tvb, pinfo, tree);
304 return tvb_captured_length(tvb);
307 /* Dissect word 0 - I/NAV Spare Word */
308 static int dissect_ubx_gal_inav_word0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
309 col_append_str(pinfo->cinfo, COL_INFO, "Word 0 (Spare Word)");
311 proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word0, tvb, 0, 16, ENC_NA);
312 proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word0);
314 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type, tvb, 0, 1, ENC_NA);
315 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_time, tvb, 0, 1, ENC_NA);
316 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_spare, tvb, 1, 11, ENC_NA);
317 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_wn, tvb, 12, 4, ENC_BIG_ENDIAN);
318 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word0_tow, tvb, 12, 4, ENC_BIG_ENDIAN);
320 return tvb_captured_length(tvb);
323 /* Dissect word 1 - Ephemeris (1/4) */
324 static int dissect_ubx_gal_inav_word1(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
325 col_append_str(pinfo->cinfo, COL_INFO, "Word 1 (Ephemeris (1/4))");
327 proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word1, tvb, 0, 16, ENC_NA);
328 proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word1);
330 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type, tvb, 0, 1, ENC_NA);
331 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_iodnav, tvb, 0, 2, ENC_BIG_ENDIAN);
332 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_t0e, tvb, 2, 2, ENC_BIG_ENDIAN);
333 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_m0, tvb, 3, 8, ENC_BIG_ENDIAN);
334 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_e, tvb, 7, 8, ENC_BIG_ENDIAN);
335 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_sqrta, tvb, 8, 8, ENC_BIG_ENDIAN);
336 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word1_reserved, tvb, 15, 1, ENC_NA);
338 return tvb_captured_length(tvb);
341 /* Dissect word 2 - Ephemeris (2/4) */
342 static int dissect_ubx_gal_inav_word2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
343 col_append_str(pinfo->cinfo, COL_INFO, "Word 2 (Ephemeris (2/4))");
345 proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word2, tvb, 0, 16, ENC_NA);
346 proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word2);
348 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type, tvb, 0, 1, ENC_NA);
349 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_iodnav, tvb, 0, 2, ENC_BIG_ENDIAN);
350 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_omega0, tvb, 2, 4, ENC_BIG_ENDIAN);
351 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_i0, tvb, 6, 4, ENC_BIG_ENDIAN);
352 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_omega, tvb, 10, 4, ENC_BIG_ENDIAN);
353 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_incl_angle_rate, tvb, 14, 2, ENC_BIG_ENDIAN);
354 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word2_reserved, tvb, 15, 1, ENC_NA);
356 return tvb_captured_length(tvb);
359 /* Dissect word 3 - Ephemeris (3/4) */
360 static int dissect_ubx_gal_inav_word3(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
361 col_append_str(pinfo->cinfo, COL_INFO, "Word 3 (Ephemeris (3/4))");
363 proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word3, tvb, 0, 16, ENC_NA);
364 proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word3);
366 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type, tvb, 0, 1, ENC_NA);
367 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_iodnav, tvb, 0, 2, ENC_BIG_ENDIAN);
368 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_omega_rate, tvb, 2, 4, ENC_BIG_ENDIAN);
369 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_delta_n, tvb, 5, 2, ENC_BIG_ENDIAN);
370 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_uc, tvb, 7, 2, ENC_BIG_ENDIAN);
371 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_us, tvb, 9, 2, ENC_BIG_ENDIAN);
372 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_rc, tvb, 11, 2, ENC_BIG_ENDIAN);
373 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_c_rs, tvb, 13, 2, ENC_BIG_ENDIAN);
374 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word3_sisa_e1_e5b, tvb, 15, 1, ENC_NA);
376 return tvb_captured_length(tvb);
379 /* Dissect word 4 - Ephemeris (4/4) */
380 static int dissect_ubx_gal_inav_word4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
381 col_append_str(pinfo->cinfo, COL_INFO, "Word 4 (Ephemeris (4/4))");
383 proto_item *ti = proto_tree_add_item(tree, hf_ubx_gal_inav_word4, tvb, 0, 16, ENC_NA);
384 proto_tree *word_tree = proto_item_add_subtree(ti, ett_ubx_gal_inav_word4);
386 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word_type, tvb, 0, 1, ENC_NA);
387 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_iodnav, tvb, 0, 2, ENC_BIG_ENDIAN);
388 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_svid, tvb, 2, 1, ENC_NA);
389 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_c_ic, tvb, 2, 4, ENC_BIG_ENDIAN);
390 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_c_is, tvb, 4, 4, ENC_BIG_ENDIAN);
391 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_t_0c, tvb, 6, 4, ENC_BIG_ENDIAN);
392 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f0, tvb, 8, 8, ENC_BIG_ENDIAN);
393 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f1, tvb, 12, 4, ENC_BIG_ENDIAN);
394 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_a_f2, tvb, 12, 4, ENC_BIG_ENDIAN);
395 proto_tree_add_item(word_tree, hf_ubx_gal_inav_word4_spare, tvb, 15, 1, ENC_NA);
397 return tvb_captured_length(tvb);
400 void proto_register_ubx_gal_inav(void) {
402 static hf_register_info hf[] = {
403 {&hf_ubx_gal_inav_even_odd, {"Even/Odd", "gal_inav.even_odd", FT_BOOLEAN, 8, TFS(&tfs_odd_even), 0x80, NULL, HFILL}},
404 {&hf_ubx_gal_inav_page_type, {"Page Type", "gal_inav.page_type", FT_UINT8, BASE_DEC, VALS(GAL_PAGE_TYPE), 0x40, NULL, HFILL}},
405 {&hf_ubx_gal_inav_type, {"Type", "gal_inav.type", FT_UINT8, BASE_DEC, NULL, 0x3f, NULL, HFILL}},
406 {&hf_ubx_gal_inav_data_122_67, {"Data (122-67)", "gal_inav.data_122_67", FT_UINT64, BASE_HEX, NULL, 0x00ffffffffffffff, NULL, HFILL}},
407 {&hf_ubx_gal_inav_data_66_17, {"Data (66-17)", "gal_inav.data_66_17", FT_UINT64, BASE_HEX, NULL, 0xffffffffffffc000, NULL, HFILL}},
408 {&hf_ubx_gal_inav_data_16_1, {"Data (16-1)", "gal_inav.data_16_1", FT_UINT64, BASE_HEX, NULL, 0x3fffc00000000000, NULL, HFILL}},
409 {&hf_ubx_gal_inav_osnma, {"OSNMA", "gal_inav.osnma", FT_UINT64, BASE_HEX, NULL, 0x00003fffffffffc0, NULL, HFILL}},
410 {&hf_ubx_gal_inav_sar_start_bit, {"Start bit", "gal_inav.sar.start_bit", FT_BOOLEAN, 32, NULL, 0x20000000, NULL, HFILL}},
411 {&hf_ubx_gal_inav_sar_long_rlm, {"Long RLM", "gal_inav.sar.long_rlm", FT_BOOLEAN, 32, NULL, 0x10000000, NULL, HFILL}},
412 {&hf_ubx_gal_inav_sar_beacon_1, {"Beacon (1/3)", "gal_inav.sar.beacon_1", FT_UINT32, BASE_HEX, NULL, 0x0fffff00, NULL, HFILL}},
413 {&hf_ubx_gal_inav_sar_rlm_data, {"RLM data", "gal_inav.sar.rlm_data", FT_UINT32, BASE_HEX, NULL, 0x0fffff00, NULL, HFILL}},
414 {&hf_ubx_gal_inav_spare, {"Spare", "gal_inav.spare", FT_UINT8, BASE_HEX, NULL, 0xc0, NULL, HFILL}},
415 {&hf_ubx_gal_inav_reserved_1, {"Reserved 1", "gal_inav.reserved_1", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
416 {&hf_ubx_gal_inav_crc, {"CRC", "gal_inav.crc", FT_UINT32, BASE_HEX, NULL, 0x3fffffc0, NULL, HFILL}},
417 {&hf_ubx_gal_inav_ssp, {"SSP", "gal_inav.ssp", FT_UINT32, BASE_HEX, VALS(GAL_SSP), 0x003fc000, NULL, HFILL}},
418 {&hf_ubx_gal_inav_tail, {"Tail", "gal_inav.tail", FT_UINT8, BASE_HEX, NULL, 0x3f, NULL, HFILL}},
419 {&hf_ubx_gal_inav_pad, {"Pad", "gal_inav.pad", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
421 // Data words
422 {&hf_ubx_gal_inav_word_type, {"Type", "gal_inav.word.type", FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL}},
424 // Word 0
425 {&hf_ubx_gal_inav_word0, {"Word 0 (Spare Word)", "gal_inav.word0", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
426 {&hf_ubx_gal_inav_word0_time, {"Time", "gal_inav.word0.time", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL}},
427 {&hf_ubx_gal_inav_word0_spare, {"Spare", "gal_inav.word0.spare", FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0, NULL, HFILL}},
428 {&hf_ubx_gal_inav_word0_wn, {"Week Number", "gal_inav.word0.wn", FT_UINT32, BASE_DEC, NULL, 0xfff00000, NULL, HFILL}},
429 {&hf_ubx_gal_inav_word0_tow, {"Time of Week", "gal_inav.word0.tow", FT_UINT32, BASE_DEC, NULL, 0x000fffff, NULL, HFILL}},
431 // Word 1
432 {&hf_ubx_gal_inav_word1, {"Word 1 (Ephemeris (1/4))", "gal_inav.word1", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
433 {&hf_ubx_gal_inav_word1_iodnav, {"IOD_nav", "gal_inav.word1.iod_nav", FT_UINT16, BASE_DEC, NULL, 0x03ff, NULL, HFILL}},
434 {&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}},
435 {&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), 0x03fffffffc000000, NULL, HFILL}},
436 {&hf_ubx_gal_inav_word1_e, {"Eccentricity (e)", "gal_inav.word1.e", FT_UINT64, BASE_CUSTOM, CF_FUNC(&fmt_e), 0x03fffffffc000000, NULL, HFILL}},
437 {&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), 0x00000003fffffffc, NULL, HFILL}},
438 {&hf_ubx_gal_inav_word1_reserved,{"Reserved", "gal_inav.word1.reserved", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL}},
440 // Word 2
441 {&hf_ubx_gal_inav_word2, {"Word 2 (Ephemeris (2/4))", "gal_inav.word2", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
442 {&hf_ubx_gal_inav_word2_iodnav, {"IOD_nav", "gal_inav.word2.iod_nav", FT_UINT16, BASE_DEC, NULL, 0x03ff, NULL, HFILL}},
443 {&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}},
444 {&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}},
445 {&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}},
446 {&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}},
447 {&hf_ubx_gal_inav_word2_reserved, {"Reserved", "gal_inav.word2.reserved", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL}},
449 // Word 3
450 {&hf_ubx_gal_inav_word3, {"Word 3 (Ephemeris (3/4))", "gal_inav.word3", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
451 {&hf_ubx_gal_inav_word3_iodnav, {"IOD_nav", "gal_inav.word3.iod_nav", FT_UINT16, BASE_DEC, NULL, 0x03ff, NULL, HFILL}},
452 {&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}},
453 {&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}},
454 {&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}},
455 {&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}},
456 {&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}},
457 {&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}},
458 {&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}},
460 // Word 4
461 {&hf_ubx_gal_inav_word4, {"Word 4 (Ephemeris (4/4))", "gal_inav.word4", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
462 {&hf_ubx_gal_inav_word4_iodnav, {"IOD_nav", "gal_inav.word4.iod_nav", FT_UINT16, BASE_DEC, NULL, 0x03ff, NULL, HFILL}},
463 {&hf_ubx_gal_inav_word4_svid, {"SVID", "gal_inav.word4.svid", FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL}},
464 {&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}},
465 {&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}},
466 {&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}},
467 {&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}},
468 {&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}},
469 {&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}},
470 {&hf_ubx_gal_inav_word4_spare, {"Spare", "gal_inav.word4.spare", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL}},
473 static int *ett[] = {
474 &ett_ubx_gal_inav,
475 &ett_ubx_gal_inav_word0,
476 &ett_ubx_gal_inav_word1,
477 &ett_ubx_gal_inav_word2,
478 &ett_ubx_gal_inav_word3,
479 &ett_ubx_gal_inav_word4,
480 &ett_ubx_gal_inav_sar,
483 proto_ubx_gal_inav = proto_register_protocol("Galileo E1-B I/NAV Navigation Message", "Galileo I/NAV", "gal_inav");
485 proto_register_field_array(proto_ubx_gal_inav, hf, array_length(hf));
486 proto_register_subtree_array(ett, array_length(ett));
488 register_dissector("ubx_gal_inav", dissect_ubx_gal_inav, proto_ubx_gal_inav);
490 ubx_gal_inav_word_dissector_table = register_dissector_table("ubx.rxm.sfrbx.gal_inav.word",
491 "Galileo I/NAV Word", proto_ubx_gal_inav, FT_UINT8, BASE_DEC);
494 void proto_reg_handoff_ubx_gal_inav(void) {
495 dissector_add_uint("ubx.rxm.sfrbx.gnssid", GNSS_ID_GALILEO, create_dissector_handle(dissect_ubx_gal_inav, proto_ubx_gal_inav));
497 dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 0, create_dissector_handle(dissect_ubx_gal_inav_word0, proto_ubx_gal_inav));
498 dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 1, create_dissector_handle(dissect_ubx_gal_inav_word1, proto_ubx_gal_inav));
499 dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 2, create_dissector_handle(dissect_ubx_gal_inav_word2, proto_ubx_gal_inav));
500 dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 3, create_dissector_handle(dissect_ubx_gal_inav_word3, proto_ubx_gal_inav));
501 dissector_add_uint("ubx.rxm.sfrbx.gal_inav.word", 4, create_dissector_handle(dissect_ubx_gal_inav_word4, proto_ubx_gal_inav));