1 /* packet-ubx-gps_l1_lnav.c
2 * Dissection of Global Positioning System (GPS) L1 C/A LNAV 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
17 #include <epan/expert.h>
18 #include <epan/packet.h>
20 #include "packet-ubx.h"
23 * Dissects GPS L1 C/A LNAV navigation messages as encoded by UBX (in
24 * UBX-RXM-SFRBX messages).
26 * UBX encodes the 30 bit words of GPS subframes as 32 bit words in little-endian.
28 * The two most significant bits of the 32 bit word can be ignored.
30 * UBX takes care of the word parity checks. So, parity checks do not have to be
31 * repeated for dissection. UBX inverts the bits of a word if the least
32 * significant parity bit (D30) of the previous word is 1 (i.e. UBX undoes the
33 * bit inverting of GPS removing the need to do so for dissection).
37 * mapping from L2 channel code ID to description
38 * see IS-GPS-200N, Section 20.3.3.3.1.2
40 static const value_string L2_CHANNEL_CODE
[] = {
49 * mapping from URA index to URA
50 * see IS-GPS-200N, Section 20.3.3.3.1.3
52 static const value_string URA_INDEX
[] = {
53 { 0, "0.00 < URA <= 2.40"},
54 { 1, "2.40 < URA <= 3.40"},
55 { 2, "3.40 < URA <= 4.85"},
56 { 3, "4.85 < URA <= 6.85"},
57 { 4, "6.85 < URA <= 9.65"},
58 { 5, "9.65 < URA <= 13.65"},
59 { 6, "13.65 < URA <= 24.00"},
60 { 7, "24.00 < URA <= 48.00"},
61 { 8, "48.00 < URA <= 96.00"},
62 { 9, "96.00 < URA <= 192.00"},
63 {10, "192.00 < URA <= 384.00"},
64 {11, "384.00 < URA <= 768.00"},
65 {12, "768.00 < URA <= 1536.00"},
66 {13, "1536.00 < URA <= 3072.00"},
67 {14, "3072.00 < URA <= 6144.00"},
68 {15, "6144.00 < URA"},
73 * mapping for SV health summary
74 * see IS-GPS-200N, Section 20.3.3.3.1.4
76 static const value_string SV_HEALTH_SUMMARY
[] = {
77 {0, "all LNAV data are OK"},
78 {1, "some or all LNAV data are bad"},
83 * mapping for codes for health of SV signal components
84 * see IS-GPS-200N, Section 20.3.3.5.1.3
86 static const value_string SV_HEALTH_CODE
[] = {
87 {0, "All Signals OK"},
88 {1, "All Signals Weak"},
89 {2, "All Signals Dead"},
90 {3, "All Signals Have No Data Modulation"},
91 {4, "L1 P Signal Weak"},
92 {5, "L1 P Signal Dead"},
93 {6, "L1 P Signal Has No Data Modulation"},
94 {7, "L2 P Signal Weak"},
95 {8, "L2 P Signal Dead"},
96 {9, "L2 P Signal Has No Data Modulation"},
97 {10, "L1C Signal Weak"},
98 {11, "L1C Signal Dead"},
99 {12, "L1C Signal Has No Data Modulation"},
100 {13, "L2C Signal Weak"},
101 {14, "L2C Signal Dead"},
102 {15, "L2C Signal Has No Data Modulation"},
103 {16, "L1 & L2 P Signal Weak"},
104 {17, "L1 & L2 P Signal Dead"},
105 {18, "L1 & L2 P Signal Has No Data Modulation"},
106 {19, "L1 & L2C Signal Weak"},
107 {20, "L1 & L2C Signal Dead"},
108 {21, "L1 & L2C Signal Has No Data Modulation"},
109 {22, "L1 Signal Weak"},
110 {23, "L1 Signal Dead"},
111 {24, "L1 Signal Has No Data Modulation"},
112 {25, "L2 Signal Weak"},
113 {26, "L2 Signal Dead"},
114 {27, "L2 Signal Has No Data Modulation"},
115 {28, "SV Is Temporarily Out (Do not use this SV during current pass)"},
116 {29, "SV Will Be Temporarily Out (Use with caution)"},
117 {30, "One Or More Signals Are Deformed, However The Relevant URA Parameters Are Valid"},
118 {31, "More Than One Combination Would Be Required To Describe Anomalies"},
122 // Initialize the protocol and registered fields
123 static int proto_ubx_gps_l1
;
125 // Telemetry Word (see IS-GPS-200N, Section 20.3.3.1)
126 static int hf_ubx_gps_l1_tlm_preamble
;
127 static int hf_ubx_gps_l1_tlm_message
;
128 static int hf_ubx_gps_l1_tlm_integrity
;
129 static int hf_ubx_gps_l1_tlm_reserved
;
130 static int hf_ubx_gps_l1_tlm_parity
;
132 // Handover Word (see IS-GPS-200N, Section 20.3.3.2)
133 static int hf_ubx_gps_l1_how_tow_count
;
134 static int hf_ubx_gps_l1_how_alert
;
135 static int hf_ubx_gps_l1_how_anti_spoof
;
136 static int hf_ubx_gps_l1_how_subframe_id
;
137 static int hf_ubx_gps_l1_how_parity_sol
;
138 static int hf_ubx_gps_l1_how_parity
;
140 // Subframe 1 (see IS-GPS-200N, Section 20.3.3.3)
141 static int hf_ubx_gps_l1_sf1
;
142 static int hf_ubx_gps_l1_sf1_week_no
;
143 static int hf_ubx_gps_l1_sf1_l2_channel_code
;
144 static int hf_ubx_gps_l1_sf1_ura_index
;
145 static int hf_ubx_gps_l1_sf1_sv_health_summary
;
146 static int hf_ubx_gps_l1_sf1_sv_health
;
147 static int hf_ubx_gps_l1_sf1_iodc_msbs
;
148 static int hf_ubx_gps_l1_sf1_w3_parity
;
149 static int hf_ubx_gps_l1_sf1_w4_l2_p_data_flag
;
150 static int hf_ubx_gps_l1_sf1_w4_reserved
;
151 static int hf_ubx_gps_l1_sf1_w4_parity
;
152 static int hf_ubx_gps_l1_sf1_w5_reserved
;
153 static int hf_ubx_gps_l1_sf1_w5_parity
;
154 static int hf_ubx_gps_l1_sf1_w6_reserved
;
155 static int hf_ubx_gps_l1_sf1_w6_parity
;
156 static int hf_ubx_gps_l1_sf1_w7_reserved
;
157 static int hf_ubx_gps_l1_sf1_w7_tgd
;
158 static int hf_ubx_gps_l1_sf1_w7_parity
;
159 static int hf_ubx_gps_l1_sf1_w8_iodc_lsbs
;
160 static int hf_ubx_gps_l1_sf1_w8_toc
;
161 static int hf_ubx_gps_l1_sf1_w8_parity
;
162 static int hf_ubx_gps_l1_sf1_w9_af2
;
163 static int hf_ubx_gps_l1_sf1_w9_af1
;
164 static int hf_ubx_gps_l1_sf1_w9_parity
;
165 static int hf_ubx_gps_l1_sf1_w10_af0
;
166 static int hf_ubx_gps_l1_sf1_w10_parity
;
168 static dissector_table_t ubx_gps_l1_sf_dissector_table
;
170 static expert_field ei_ubx_gps_l1_tlm_preamble
;
171 static expert_field ei_ubx_gps_l1_how_tow_count
;
172 static expert_field ei_ubx_gps_l1_how_subframe_id
;
174 static int ett_ubx_gps_l1
;
175 static int ett_ubx_gps_l1_tlm
;
176 static int ett_ubx_gps_l1_how
;
177 static int ett_ubx_gps_l1_sf1_w3
;
178 static int ett_ubx_gps_l1_sf1_w4
;
179 static int ett_ubx_gps_l1_sf1_w5
;
180 static int ett_ubx_gps_l1_sf1_w6
;
181 static int ett_ubx_gps_l1_sf1_w7
;
182 static int ett_ubx_gps_l1_sf1_w8
;
183 static int ett_ubx_gps_l1_sf1_w9
;
184 static int ett_ubx_gps_l1_sf1_w10
;
186 /* Format TOW count */
187 static void fmt_tow_count(char *label
, int32_t c
) {
188 unsigned tow
= c
<< 2;
189 snprintf(label
, ITEM_LABEL_LENGTH
, "%d (TOW: %.1fs)", c
, tow
* 1.5);
192 /* Format Clock Data Reference Time t_OC */
193 static void fmt_t_oc(char *label
, int32_t i
) {
194 unsigned t_oc
= i
<< 4;
195 snprintf(label
, ITEM_LABEL_LENGTH
, "%ds", t_oc
);
198 /* Dissect GPS L1 C/A LNAV navigation message */
199 static int dissect_ubx_gps_l1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
200 uint32_t subframe_id
= (tvb_get_uint32(tvb
, 4, ENC_LITTLE_ENDIAN
) & 0x00000700) >> 8;
202 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GPS L1 LNAV");
203 col_clear(pinfo
->cinfo
, COL_INFO
);
204 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Subframe %i", subframe_id
);
206 proto_tree
*gps_l1_tree
= proto_tree_add_subtree_format(tree
, tvb
, 0, 40, ett_ubx_gps_l1
, NULL
, "GPS L1 LNAV (Subframe %i)", subframe_id
);
208 // send the subframe to the next dissector
209 if (!dissector_try_uint(ubx_gps_l1_sf_dissector_table
, subframe_id
, tvb
, pinfo
, gps_l1_tree
)) {
210 call_data_dissector(tvb
, pinfo
, tree
);
213 return tvb_captured_length(tvb
);
216 // Dissect the telemetry (TLM) word
217 static void dissect_ubx_gps_l1_tlm(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
) {
218 proto_tree
*tlm_tree
= proto_tree_add_subtree_format(tree
, tvb
, 0, 4, ett_ubx_gps_l1_tlm
, NULL
, "Word 1: Telemetry");
220 uint32_t tlm_preamble
;
221 proto_item
* pi_tlm_preamble
= proto_tree_add_item_ret_uint(tlm_tree
, hf_ubx_gps_l1_tlm_preamble
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
, &tlm_preamble
);
222 if (tlm_preamble
!= 0x8b) {
223 expert_add_info_format(pinfo
, pi_tlm_preamble
, &ei_ubx_gps_l1_tlm_preamble
, "Invalid preamble");
226 proto_tree_add_item(tlm_tree
, hf_ubx_gps_l1_tlm_message
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
227 proto_tree_add_item(tlm_tree
, hf_ubx_gps_l1_tlm_integrity
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
228 proto_tree_add_item(tlm_tree
, hf_ubx_gps_l1_tlm_reserved
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
229 proto_tree_add_item(tlm_tree
, hf_ubx_gps_l1_tlm_parity
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
232 // Dissect the handover word (HOW)
233 static void dissect_ubx_gps_l1_how(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
) {
234 uint32_t subframe_id
;
236 proto_tree
*how_tree
= proto_tree_add_subtree_format(tree
, tvb
, 4, 4, ett_ubx_gps_l1_how
, NULL
, "Word 2: Handover");
239 proto_item
* pi_how_tow_count
= proto_tree_add_item_ret_uint(how_tree
, hf_ubx_gps_l1_how_tow_count
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
, &tow_count
);
240 if (tow_count
> 100799) {
241 expert_add_info_format(pinfo
, pi_how_tow_count
, &ei_ubx_gps_l1_how_tow_count
, "Invalid TOW count");
244 proto_tree_add_item(how_tree
, hf_ubx_gps_l1_how_alert
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
245 proto_tree_add_item(how_tree
, hf_ubx_gps_l1_how_anti_spoof
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
247 proto_item
* pi_how_sf_id
= proto_tree_add_item_ret_uint(how_tree
, hf_ubx_gps_l1_how_subframe_id
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
, &subframe_id
);
248 if (subframe_id
> 5) {
249 expert_add_info_format(pinfo
, pi_how_sf_id
, &ei_ubx_gps_l1_how_subframe_id
, "Invalid subframe ID");
252 proto_tree_add_item(how_tree
, hf_ubx_gps_l1_how_parity_sol
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
253 proto_tree_add_item(how_tree
, hf_ubx_gps_l1_how_parity
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
256 /* Dissect subframe 1 */
257 static int dissect_ubx_gps_l1_sf1(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
) {
258 dissect_ubx_gps_l1_tlm(tvb
, pinfo
, tree
, data
);
259 dissect_ubx_gps_l1_how(tvb
, pinfo
, tree
, data
);
261 // subframe 1, word 3
262 proto_tree
*w3_tree
= proto_tree_add_subtree_format(tree
, tvb
, 8, 4, ett_ubx_gps_l1_sf1_w3
, NULL
, "Word 3");
263 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_week_no
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
264 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_l2_channel_code
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
265 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_ura_index
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
266 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_sv_health_summary
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
267 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_sv_health
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
268 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_iodc_msbs
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
269 proto_tree_add_item(w3_tree
, hf_ubx_gps_l1_sf1_w3_parity
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
271 // subframe 1, word 4
272 proto_tree
*w4_tree
= proto_tree_add_subtree_format(tree
, tvb
, 12, 4, ett_ubx_gps_l1_sf1_w4
, NULL
, "Word 4");
273 proto_tree_add_item(w4_tree
, hf_ubx_gps_l1_sf1_w4_l2_p_data_flag
, tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
274 proto_tree_add_item(w4_tree
, hf_ubx_gps_l1_sf1_w4_reserved
, tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
275 proto_tree_add_item(w4_tree
, hf_ubx_gps_l1_sf1_w4_parity
, tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
278 // subframe 1, word 5
279 proto_tree
*w5_tree
= proto_tree_add_subtree_format(tree
, tvb
, 16, 4, ett_ubx_gps_l1_sf1_w5
, NULL
, "Word 5");
280 proto_tree_add_item(w5_tree
, hf_ubx_gps_l1_sf1_w5_reserved
, tvb
, 16, 4, ENC_LITTLE_ENDIAN
);
281 proto_tree_add_item(w5_tree
, hf_ubx_gps_l1_sf1_w5_parity
, tvb
, 16, 4, ENC_LITTLE_ENDIAN
);
283 // subframe 1, word 6
284 proto_tree
*w6_tree
= proto_tree_add_subtree_format(tree
, tvb
, 20, 4, ett_ubx_gps_l1_sf1_w6
, NULL
, "Word 6");
285 proto_tree_add_item(w6_tree
, hf_ubx_gps_l1_sf1_w6_reserved
, tvb
, 20, 4, ENC_LITTLE_ENDIAN
);
286 proto_tree_add_item(w6_tree
, hf_ubx_gps_l1_sf1_w6_parity
, tvb
, 20, 4, ENC_LITTLE_ENDIAN
);
288 // subframe 1, word 7
289 proto_tree
*w7_tree
= proto_tree_add_subtree_format(tree
, tvb
, 24, 4, ett_ubx_gps_l1_sf1_w7
, NULL
, "Word 7");
290 proto_tree_add_item(w7_tree
, hf_ubx_gps_l1_sf1_w7_reserved
, tvb
, 24, 4, ENC_LITTLE_ENDIAN
);
291 proto_tree_add_item(w7_tree
, hf_ubx_gps_l1_sf1_w7_tgd
, tvb
, 24, 4, ENC_LITTLE_ENDIAN
);
292 proto_tree_add_item(w7_tree
, hf_ubx_gps_l1_sf1_w7_parity
, tvb
, 24, 4, ENC_LITTLE_ENDIAN
);
294 // subframe 1, word 8
295 proto_tree
*w8_tree
= proto_tree_add_subtree_format(tree
, tvb
, 28, 4, ett_ubx_gps_l1_sf1_w8
, NULL
, "Word 8");
296 proto_tree_add_item(w8_tree
, hf_ubx_gps_l1_sf1_w8_iodc_lsbs
, tvb
, 28, 4, ENC_LITTLE_ENDIAN
);
297 proto_tree_add_item(w8_tree
, hf_ubx_gps_l1_sf1_w8_toc
, tvb
, 28, 4, ENC_LITTLE_ENDIAN
);
298 proto_tree_add_item(w8_tree
, hf_ubx_gps_l1_sf1_w8_parity
, tvb
, 28, 4, ENC_LITTLE_ENDIAN
);
300 // subframe 1, word 9
301 proto_tree
*w9_tree
= proto_tree_add_subtree_format(tree
, tvb
, 32, 4, ett_ubx_gps_l1_sf1_w9
, NULL
, "Word 9");
302 proto_tree_add_item(w9_tree
, hf_ubx_gps_l1_sf1_w9_af2
, tvb
, 32, 4, ENC_LITTLE_ENDIAN
);
303 proto_tree_add_item(w9_tree
, hf_ubx_gps_l1_sf1_w9_af1
, tvb
, 32, 4, ENC_LITTLE_ENDIAN
);
304 proto_tree_add_item(w9_tree
, hf_ubx_gps_l1_sf1_w9_parity
, tvb
, 32, 4, ENC_LITTLE_ENDIAN
);
306 // subframe 1, word 10
307 proto_tree
*w10_tree
= proto_tree_add_subtree_format(tree
, tvb
, 36, 4, ett_ubx_gps_l1_sf1_w10
, NULL
, "Word 10");
308 proto_tree_add_item(w10_tree
, hf_ubx_gps_l1_sf1_w10_af0
, tvb
, 36, 4, ENC_LITTLE_ENDIAN
);
309 proto_tree_add_item(w10_tree
, hf_ubx_gps_l1_sf1_w10_parity
, tvb
, 36, 4, ENC_LITTLE_ENDIAN
);
311 return tvb_captured_length(tvb
);
314 void proto_register_ubx_gps_l1(void) {
316 static hf_register_info hf
[] = {
318 {&hf_ubx_gps_l1_tlm_preamble
, {"Preamble", "gps_l1.tlm.preamble", FT_UINT32
, BASE_HEX
, NULL
, 0x3fc00000, NULL
, HFILL
}},
319 {&hf_ubx_gps_l1_tlm_message
, {"Message", "gps_l1.tlm.message", FT_UINT32
, BASE_HEX
, NULL
, 0x003fff00, NULL
, HFILL
}},
320 {&hf_ubx_gps_l1_tlm_integrity
, {"Integrity Status Flag (ISF)", "gps_l1.tlm.integrity", FT_BOOLEAN
, 32, NULL
, 0x00000080, NULL
, HFILL
}},
321 {&hf_ubx_gps_l1_tlm_reserved
, {"Reserved", "gps_l1.tlm.reserved", FT_UINT32
, BASE_HEX
, NULL
, 0x00000040, NULL
, HFILL
}},
322 {&hf_ubx_gps_l1_tlm_parity
, {"Parity", "gps_l1.tlm.parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
325 {&hf_ubx_gps_l1_how_tow_count
, {"Time-of-Week (TOW) Count", "gps_l1.how.tow_count", FT_UINT32
, BASE_CUSTOM
, CF_FUNC(&fmt_tow_count
), 0x3fffe000, NULL
, HFILL
}},
326 {&hf_ubx_gps_l1_how_alert
, {"Alert", "gps_l1.how.alert", FT_BOOLEAN
, 32, NULL
, 0x00001000, NULL
, HFILL
}},
327 {&hf_ubx_gps_l1_how_anti_spoof
, {"Anti-Spoof (A-S)", "gps_l1.how.anti_spoof", FT_BOOLEAN
, 32, NULL
, 0x00000800, NULL
, HFILL
}},
328 {&hf_ubx_gps_l1_how_subframe_id
, {"Subframe ID", "gps_l1.how.subframe_id", FT_UINT32
, BASE_DEC
, NULL
, 0x00000700, NULL
, HFILL
}},
329 {&hf_ubx_gps_l1_how_parity_sol
, {"Solved for parity zero bits", "gps_l1.how.parity_sol", FT_UINT32
, BASE_HEX
, NULL
, 0x000000c0, NULL
, HFILL
}},
330 {&hf_ubx_gps_l1_how_parity
, {"Parity", "gps_l1.how.parity", FT_UINT32
, BASE_DEC
, NULL
, 0x0000003f, NULL
, HFILL
}},
333 {&hf_ubx_gps_l1_sf1
, {"Subframe 1", "gps_l1.sf1", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
334 {&hf_ubx_gps_l1_sf1_week_no
, {"Week Number", "gps_l1.sf1.week_number", FT_UINT32
, BASE_DEC
, NULL
, 0x3ff00000, NULL
, HFILL
}},
335 {&hf_ubx_gps_l1_sf1_l2_channel_code
, {"L2 Channel Code", "gps_l1.sf1.l2_channel_code", FT_UINT32
, BASE_HEX
, VALS(L2_CHANNEL_CODE
), 0x000c0000, NULL
, HFILL
}},
336 {&hf_ubx_gps_l1_sf1_ura_index
, {"URA Index", "gps_l1.sf1.ura_index", FT_UINT32
, BASE_HEX
, VALS(URA_INDEX
), 0x0003c000, NULL
, HFILL
}},
337 {&hf_ubx_gps_l1_sf1_sv_health_summary
, {"SV Health Summary", "gps_l1.sf1.sv_health_summary", FT_UINT32
, BASE_HEX
, VALS(SV_HEALTH_SUMMARY
), 0x00002000, NULL
, HFILL
}},
338 {&hf_ubx_gps_l1_sf1_sv_health
, {"SV's Signal Component Health Status", "gps_l1.sf1.sv_health", FT_UINT32
, BASE_HEX
, VALS(SV_HEALTH_CODE
), 0x00001f00, NULL
, HFILL
}},
339 {&hf_ubx_gps_l1_sf1_iodc_msbs
, {"Issue of Data Clock (IODC) MSBs", "gps_l1.sf1.iodc_msbs", FT_UINT32
, BASE_HEX
, NULL
, 0x000000c0, NULL
, HFILL
}},
340 {&hf_ubx_gps_l1_sf1_w3_parity
, {"Parity", "gps_l1.sf1.w3_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
341 {&hf_ubx_gps_l1_sf1_w4_l2_p_data_flag
, {"L2 P Data Flag", "gps_l1.sf1.l2_p_data_flag", FT_BOOLEAN
, 32, NULL
, 0x20000000, NULL
, HFILL
}},
342 {&hf_ubx_gps_l1_sf1_w4_reserved
, {"Reserved", "gps_l1.sf1.w4_reserved", FT_UINT32
, BASE_HEX
, NULL
, 0x1fffffc0, NULL
, HFILL
}},
343 {&hf_ubx_gps_l1_sf1_w4_parity
, {"Parity", "gps_l1.sf1.w4_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
344 {&hf_ubx_gps_l1_sf1_w5_reserved
, {"Reserved", "gps_l1.sf1.w5_reserved", FT_UINT32
, BASE_HEX
, NULL
, 0x3fffffc0, NULL
, HFILL
}},
345 {&hf_ubx_gps_l1_sf1_w5_parity
, {"Parity", "gps_l1.sf1.w5_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
346 {&hf_ubx_gps_l1_sf1_w6_reserved
, {"Reserved", "gps_l1.sf1.w6_reserved", FT_UINT32
, BASE_HEX
, NULL
, 0x3fffffc0, NULL
, HFILL
}},
347 {&hf_ubx_gps_l1_sf1_w6_parity
, {"Parity", "gps_l1.sf1.w6_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
348 {&hf_ubx_gps_l1_sf1_w7_reserved
, {"Reserved", "gps_l1.sf1.w7_reserved", FT_UINT32
, BASE_HEX
, NULL
, 0x3fffc000, NULL
, HFILL
}},
349 {&hf_ubx_gps_l1_sf1_w7_tgd
, {"Estimated Group Delay Differential T_GD", "gps_l1.sf1.w7_tgd", FT_INT32
, BASE_DEC
, NULL
, 0x00003fc0, NULL
, HFILL
}},
350 {&hf_ubx_gps_l1_sf1_w7_parity
, {"Parity", "gps_l1.sf1.w7_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
351 {&hf_ubx_gps_l1_sf1_w8_iodc_lsbs
, {"Issue of Data Clock (IODC) LSBs", "gps_l1.sf1.w8_iodc_lsbs", FT_UINT32
, BASE_HEX
, NULL
, 0x3fc00000, NULL
, HFILL
}},
352 {&hf_ubx_gps_l1_sf1_w8_toc
, {"Clock Data Reference Time t_OC", "gps_l1.sf1.w8_toc", FT_UINT32
, BASE_CUSTOM
, CF_FUNC(&fmt_t_oc
), 0x003fffc0, NULL
, HFILL
}},
353 {&hf_ubx_gps_l1_sf1_w8_parity
, {"Parity", "gps_l1.sf1.w8_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
354 {&hf_ubx_gps_l1_sf1_w9_af2
, {"Drift Rate Correction Coefficient a_f2", "gps_l1.sf1.w9_af2", FT_INT32
, BASE_DEC
, NULL
, 0x3fc00000, NULL
, HFILL
}},
355 {&hf_ubx_gps_l1_sf1_w9_af1
, {"SV Clock Drift Correction Coefficient a_f1", "gps_l1.sf1.w9_af1", FT_INT32
, BASE_DEC
, NULL
, 0x003fffc0, NULL
, HFILL
}},
356 {&hf_ubx_gps_l1_sf1_w9_parity
, {"Parity", "gps_l1.sf1.w9_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
357 {&hf_ubx_gps_l1_sf1_w10_af0
, {"SV Clock Bias Correction Coefficient a_f0", "gps_l1.sf1.w10_af0", FT_INT32
, BASE_DEC
, NULL
, 0x3fffffc0, NULL
, HFILL
}},
358 {&hf_ubx_gps_l1_sf1_w10_parity
, {"Parity", "gps_l1.sf1.w10_parity", FT_UINT32
, BASE_HEX
, NULL
, 0x0000003f, NULL
, HFILL
}},
361 expert_module_t
*expert_ubx_gps_l1
;
363 static ei_register_info ei
[] = {
364 {&ei_ubx_gps_l1_tlm_preamble
, {"gps_l1.tlm.preamble", PI_PROTOCOL
, PI_WARN
, "Illegal preamble", EXPFILL
}},
365 {&ei_ubx_gps_l1_how_tow_count
, {"gps_l1.how.tow_count", PI_PROTOCOL
, PI_WARN
, "Illegal TOW count", EXPFILL
}},
366 {&ei_ubx_gps_l1_how_subframe_id
, {"gps_l1.how.subframe_id", PI_PROTOCOL
, PI_WARN
, "Illegal subframe ID", EXPFILL
}},
369 static int *ett
[] = {
373 &ett_ubx_gps_l1_sf1_w3
,
374 &ett_ubx_gps_l1_sf1_w4
,
375 &ett_ubx_gps_l1_sf1_w5
,
376 &ett_ubx_gps_l1_sf1_w6
,
377 &ett_ubx_gps_l1_sf1_w7
,
378 &ett_ubx_gps_l1_sf1_w8
,
379 &ett_ubx_gps_l1_sf1_w9
,
380 &ett_ubx_gps_l1_sf1_w10
,
383 proto_ubx_gps_l1
= proto_register_protocol("GPS L1 Navigation Message", "GPS L1", "gps_l1");
385 register_dissector("ubx_gps_l1", dissect_ubx_gps_l1
, proto_ubx_gps_l1
);
387 proto_register_field_array(proto_ubx_gps_l1
, hf
, array_length(hf
));
388 proto_register_subtree_array(ett
, array_length(ett
));
390 expert_ubx_gps_l1
= expert_register_protocol(proto_ubx_gps_l1
);
391 expert_register_field_array(expert_ubx_gps_l1
, ei
, array_length(ei
));
393 ubx_gps_l1_sf_dissector_table
= register_dissector_table("ubx.rxm.sfrbx.gps_l1.sf",
394 "GPS L1 LNAV Subframe", proto_ubx_gps_l1
, FT_UINT8
, BASE_DEC
);
397 void proto_reg_handoff_ubx_gps_l1(void) {
398 dissector_add_uint("ubx.rxm.sfrbx.gnssid", GNSS_ID_GPS
,
399 create_dissector_handle(dissect_ubx_gps_l1
, proto_ubx_gps_l1
));
401 dissector_add_uint("ubx.rxm.sfrbx.gps_l1.sf", 1,
402 create_dissector_handle(dissect_ubx_gps_l1_sf1
, proto_ubx_gps_l1
));