Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ansi_801.c
Line
Count
Source
1
/* packet-ansi_801.c
2
 * Routines for ANSI IS-801 (Location Services (PLD)) dissection
3
 *
4
 *   Location Services (Position Determination Service)
5
 *      3GPP2 C.S0022-0 v1.0  IS-801
6
 *
7
 *   Location Services (Position Determination Service)
8
 *      3GPP2 C.S0022-0-1 v1.0  IS-801 Addendum
9
 *
10
 * Copyright 2004, Michael Lum <mlum [AT] telostech.com>
11
 * In association with Telos Technology Inc.
12
 * Copyright 2007, Michael Lum <michael.lum [AT] utstar.com>
13
 * In association with UTStarcom Inc.
14
 *
15
 * Wireshark - Network traffic analyzer
16
 * By Gerald Combs <gerald@wireshark.org>
17
 * Copyright 1998 Gerald Combs
18
 *
19
 * SPDX-License-Identifier: GPL-2.0-or-later
20
 */
21
22
#include "config.h"
23
24
#include <math.h>
25
26
#include <epan/packet.h>
27
#include <epan/expert.h>
28
#include <epan/tfs.h>
29
#include <epan/unit_strings.h>
30
#include <wsutil/array.h>
31
32
void proto_register_ansi_801(void);
33
void proto_reg_handoff_ansi_801(void);
34
35
28
#define ANSI_801_FORWARD  0
36
28
#define ANSI_801_REVERSE  1
37
38
/* Initialize the subtree pointers */
39
static int ett_ansi_801;
40
static int ett_gps;
41
static int ett_loc;
42
43
/* Initialize the protocol and registered fields */
44
static int proto_ansi_801;
45
static int hf_ansi_801_for_req_type;
46
static int hf_ansi_801_for_rsp_type;
47
static int hf_ansi_801_rev_req_type;
48
static int hf_ansi_801_rev_rsp_type;
49
static int hf_ansi_801_for_sess_tag;
50
static int hf_ansi_801_rev_sess_tag;
51
static int hf_ansi_801_sess_tag;
52
53
static int hf_ansi_801_time_ref_cdma;
54
static int hf_ansi_801_lat;
55
static int hf_ansi_801_long;
56
static int hf_ansi_801_loc_uncrtnty_ang;
57
static int hf_ansi_801_loc_uncrtnty_a;
58
static int hf_ansi_801_loc_uncrtnty_p;
59
static int hf_ansi_801_fix_type;
60
static int hf_ansi_801_velocity_incl;
61
static int hf_ansi_801_velocity_hor;
62
static int hf_ansi_801_heading;
63
static int hf_ansi_801_velocity_ver;
64
static int hf_ansi_801_clock_incl;
65
static int hf_ansi_801_clock_bias;
66
static int hf_ansi_801_clock_drift;
67
static int hf_ansi_801_height_incl;
68
static int hf_ansi_801_height;
69
static int hf_ansi_801_loc_uncrtnty_v;
70
static int hf_ansi_801_reserved_bits;
71
72
static int hf_ansi_801_bad_sv_present;
73
static int hf_ansi_801_num_bad_sv;
74
static int hf_ansi_801_bad_sv_prn_num;
75
static int hf_ansi_801_dopp_req;
76
static int hf_ansi_801_add_dopp_req;
77
static int hf_ansi_801_code_ph_par_req;
78
static int hf_ansi_801_az_el_req;
79
80
static int hf_ansi_801_pref_resp_qual;
81
static int hf_ansi_801_num_fixes;
82
static int hf_ansi_801_t_betw_fixes;
83
static int hf_ansi_801_offset_req;
84
85
/* Generated from convert_proto_tree_add_text.pl */
86
static int hf_ansi_801_for_message_number_responsesF0;
87
static int hf_ansi_801_apdc_id;
88
static int hf_ansi_801_num_sv_p32;
89
static int hf_ansi_801_regulatory_services_indicator;
90
static int hf_ansi_801_session_source;
91
static int hf_ansi_801_reserved8_E0;
92
static int hf_ansi_801_action_time;
93
static int hf_ansi_801_rev_message_number_responsesF0;
94
static int hf_ansi_801_reserved24_3;
95
static int hf_ansi_801_cancellation_type;
96
static int hf_ansi_801_gps_navigation_message_bits;
97
static int hf_ansi_801_num_dr_p;
98
static int hf_ansi_801_rev_message_number_requests8;
99
static int hf_ansi_801_reserved8_F0;
100
static int hf_ansi_801_for_req_loc_clock_correction_for_gps_time;
101
static int hf_ansi_801_for_response_length;
102
static int hf_ansi_801_session_end;
103
static int hf_ansi_801_reserved8_1F;
104
static int hf_ansi_801_part_num;
105
static int hf_ansi_801_dr_size;
106
static int hf_ansi_801_reserved_24_700;
107
static int hf_ansi_801_for_message_number_responses0F;
108
static int hf_ansi_801_rev_message_number_requests16;
109
static int hf_ansi_801_lcc_capable_using_location_assistance_spherical;
110
static int hf_ansi_801_part_num32;
111
static int hf_ansi_801_part_num16;
112
static int hf_ansi_801_reserved8_07;
113
static int hf_ansi_801_reserved24_1;
114
static int hf_ansi_801_reserved_24_F80000;
115
static int hf_ansi_801_extended_base_station_almanac;
116
static int hf_ansi_801_no_outstanding_request_element;
117
static int hf_ansi_801_for_request_length;
118
static int hf_ansi_801_week_num;
119
static int hf_ansi_801_total_parts16;
120
static int hf_ansi_801_pd_message_type;
121
static int hf_ansi_801_total_parts32;
122
static int hf_ansi_801_alpha_and_beta_parameters;
123
static int hf_ansi_801_lcc_using_gps_ephemeris_assistance;
124
static int hf_ansi_801_rev_request_length;
125
static int hf_ansi_801_reserved8_7F;
126
static int hf_ansi_801_unsolicited_response_indicator;
127
static int hf_ansi_801_autonomous_location_calculation_capable;
128
static int hf_ansi_801_gps_almanac_correction;
129
static int hf_ansi_801_total_parts;
130
static int hf_ansi_801_session_start;
131
static int hf_ansi_801_ref_bit_num;
132
static int hf_ansi_801_aflt_lcc;
133
static int hf_ansi_801_reject_reason;
134
static int hf_ansi_801_gps_ephemeris;
135
static int hf_ansi_801_pre_programmed_location;
136
static int hf_ansi_801_rev_response_length;
137
static int hf_ansi_801_afltc_id;
138
static int hf_ansi_801_rev_req_loc_height_information;
139
static int hf_ansi_801_reserved8_01;
140
static int hf_ansi_801_pilot_ph_cap;
141
static int hf_ansi_801_gps_acquisition_assistance;
142
static int hf_ansi_801_coordinate_type_requested;
143
static int hf_ansi_801_gps_almanac;
144
static int hf_ansi_801_rev_req_loc_velocity_information;
145
static int hf_ansi_801_gps_autonomous_acquisition_capable;
146
static int hf_ansi_801_num_sv_p16;
147
static int hf_ansi_801_mob_sys_t_offset;
148
static int hf_ansi_801_desired_pilot_phase_resolution;
149
static int hf_ansi_801_for_req_loc_velocity_information;
150
static int hf_ansi_801_reserved8_0F;
151
static int hf_ansi_801_hybrid_gps_and_aflt_lcc;
152
static int hf_ansi_801_gps_acq_cap;
153
static int hf_ansi_801_gps_sensitivity_assistance;
154
static int hf_ansi_801_ms_ls_rev;
155
static int hf_ansi_801_reject_request_type;
156
static int hf_ansi_801_ms_mode;
157
static int hf_ansi_801_bs_ls_rev;
158
static int hf_ansi_801_ref_pn;
159
static int hf_ansi_801_rev_message_number_responses0F;
160
static int hf_ansi_801_for_req_loc_height_information;
161
static int hf_ansi_801_gps_capability_indicator;
162
static int hf_ansi_801_rev_req_loc_clock_correction_for_gps_time;
163
static int hf_ansi_801_data_records;
164
static int hf_ansi_801_for_message_number_requests8;
165
static int hf_ansi_801_subframes_4_and_5;
166
static int hf_ansi_801_use_action_time_indicator;
167
static int hf_ansi_801_lcc_using_gps_almanac_assistance;
168
static int hf_ansi_801_lcc_using_gps_almanac_correction;
169
static int hf_ansi_801_pd_message_len;
170
static int hf_ansi_801_lcc_using_location_assistance_cartesian;
171
static int hf_ansi_801_for_message_number_requests16;
172
static int hf_ansi_801_reserved_24_7;
173
static int hf_ansi_801_loc_calc_cap;
174
static int hf_ansi_801_toa;
175
static int hf_ansi_801_data;
176
static int hf_ansi_801_proprietary_data;
177
static int hf_ansi_801_time_ref_ms;
178
static int hf_ansi_801_time_of_almanac;
179
static int hf_ansi_801_gps_week_number;
180
181
182
static expert_field ei_ansi_801_extraneous_data;
183
static expert_field ei_ansi_801_short_data;
184
static expert_field ei_ansi_801_unexpected_length;
185
186
187
static dissector_handle_t ansi_801_handle;
188
189
/* PARAM FUNCTIONS */
190
191
#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len)     \
192
0
  if ((edc_len) > (edc_max_len))         \
193
0
  {               \
194
0
    proto_tree_add_expert(tree, pinfo, &ei_ansi_801_extraneous_data, tvb, \
195
0
            offset, (edc_len) - (edc_max_len)); \
196
0
  }
197
198
#define SHORT_DATA_CHECK(sdc_len, sdc_min_len)        \
199
0
  if ((sdc_len) < (sdc_min_len))         \
200
0
  {               \
201
0
    proto_tree_add_expert(tree, pinfo, &ei_ansi_801_short_data, tvb,  \
202
0
            offset, (sdc_len)); \
203
0
    return;             \
204
0
  }
205
206
#define EXACT_DATA_CHECK(edc_len, edc_eq_len)       \
207
  if ((edc_len) != (edc_eq_len))          \
208
  {               \
209
    proto_tree_add_expert(tree, pinfo, &ei_ansi_801_unexpected_length, tvb, \
210
            offset, (edc_len)); \
211
    return;             \
212
  }
213
214
215
/*
216
 * Table 3.2-4 for PD_MSG_TYPE = '0000000'
217
 */
218
static const value_string for_req_type_strings[] = {
219
  { 0,  "Reserved" },
220
  { 1,  "Request Location Response" },
221
  { 2,  "Request MS Information" },
222
  { 3,  "Request Autonomous Measurement Weighting Factors" },
223
  { 4,  "Request Pseudorange Measurement" },
224
  { 5,  "Request Pilot Phase Measurement" },
225
  { 6,  "Request Time Offset Measurement" },
226
  { 7,  "Request Cancellation" },
227
  { 0, NULL },
228
};
229
140
#define NUM_FOR_REQ_TYPE array_length(for_req_type_strings)
230
static int ett_for_req_type[NUM_FOR_REQ_TYPE];
231
232
static const value_string for_rsp_type_strings[] = {
233
  { 0,  "Reject" },
234
  { 2,  "Provide BS Capabilities" },
235
  { 4,  "Provide GPS Acquisition Assistance" },
236
  { 6,  "Provide GPS Location Assistance Spherical Coordinates" },
237
  { 7,  "Provide GPS Location Assistance Cartesian Coordinates" },
238
  { 5,  "Provide GPS Sensitivity Assistance" },
239
  { 3,  "Provide Base Station Almanac" },
240
  { 8,  "Provide GPS Almanac" },
241
  { 9,  "Provide GPS Ephemeris" },
242
  { 10, "Provide GPS Navigation Message Bits" },
243
  { 1,  "Provide Location Response" },
244
  { 11, "Provide GPS Almanac Correction" },
245
  { 12, "Provide GPS Satellite Health Information" },
246
  { 0, NULL },
247
};
248
210
#define NUM_FOR_RSP_TYPE array_length(for_rsp_type_strings)
249
static int ett_for_rsp_type[NUM_FOR_RSP_TYPE];
250
251
252
static const value_string rev_rsp_type_strings[] = {
253
  { 0,  "Reject" },
254
  { 2,  "Provide MS Information" },
255
  { 3,  "Provide Autonomous Measurement Weighting Factors" },
256
  { 4,  "Provide Pseudorange Measurement" },
257
  { 5,  "Provide Pilot Phase Measurement" },
258
  { 1,  "Provide Location Response" },
259
  { 6,  "Provide Time Offset Measurement" },
260
  { 7,  "Provide Cancellation Acknowledgement" },
261
  { 0, NULL },
262
};
263
140
#define NUM_REV_RSP_TYPE array_length(rev_rsp_type_strings)
264
static int ett_rev_rsp_type[NUM_REV_RSP_TYPE];
265
266
/*
267
 * Table 2.2-5 for PD_MSG_TYPE = '0000000'
268
 */
269
static const value_string rev_req_type_strings[] = {
270
  { 0,  "Reserved" },
271
  { 2,  "Request BS Capabilities" },
272
  { 4,  "Request GPS Acquisition Assistance" },
273
  { 6,  "Request GPS Location Assistance" },
274
  { 7,  "Reserved" },
275
  { 5,  "Request GPS Sensitivity Assistance" },
276
  { 3,  "Request Base Station Almanac" },
277
  { 8,  "Request GPS Almanac" },
278
  { 9,  "Request GPS Ephemeris" },
279
  { 10, "Request GPS Navigation Message Bits" },
280
  { 1,  "Request Location Response" },
281
  { 11, "Request GPS Almanac Correction" },
282
  { 12, "Request GPS Satellite Health Information" },
283
  { 0, NULL },
284
};
285
210
#define NUM_REV_REQ_TYPE array_length(rev_req_type_strings)
286
static int ett_rev_req_type[NUM_REV_REQ_TYPE];
287
288
static const value_string regulatory_services_indicator_vals[] = {
289
  { 0,  "No Regulatory service" },
290
  { 1,  "Emergency service" },
291
  { 2,  "Reserved" },
292
  { 3,  "Reserved" },
293
  { 0, NULL },
294
};
295
296
static const true_false_string tfs_desired_pilot_phase_resolution = { "at least 1/8th PN chip resolution", "at least 1 PN chip resolution" };
297
static const true_false_string tfs_spherical_cartesian = { "Spherical", "Cartesian" };
298
299
static const unit_name_string units_time_of_almanac = { " (in units of 4096 seconds)", NULL };
300
static const unit_name_string units_gps_week_number = { " (8 least significant bits)", NULL };
301
302
static void
303
for_req_pseudo_meas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
304
0
{
305
0
  uint32_t  saved_offset = offset;
306
307
0
  SHORT_DATA_CHECK(len, 3);
308
309
  /* PREF_RESP_QUAL */
310
0
  proto_tree_add_item(tree, hf_ansi_801_pref_resp_qual, tvb, offset, 3, ENC_BIG_ENDIAN);
311
0
  proto_tree_add_item(tree, hf_ansi_801_num_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
312
0
  proto_tree_add_item(tree, hf_ansi_801_t_betw_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
313
0
  proto_tree_add_item(tree, hf_ansi_801_offset_req, tvb, offset, 3, ENC_BIG_ENDIAN);
314
0
  proto_tree_add_item(tree, hf_ansi_801_reserved_24_7, tvb, offset, 3, ENC_BIG_ENDIAN);
315
0
  offset += 3;
316
317
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
318
319
0
}
320
321
static void
322
for_req_pilot_ph_meas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
323
0
{
324
0
  uint32_t  saved_offset;
325
326
0
  SHORT_DATA_CHECK(len, 3);
327
328
0
  saved_offset = offset;
329
330
0
  proto_tree_add_item(tree, hf_ansi_801_pref_resp_qual, tvb, offset, 3, ENC_BIG_ENDIAN);
331
0
  proto_tree_add_item(tree, hf_ansi_801_num_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
332
0
  proto_tree_add_item(tree, hf_ansi_801_t_betw_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
333
0
  proto_tree_add_item(tree, hf_ansi_801_offset_req, tvb, offset, 3, ENC_BIG_ENDIAN);
334
0
  proto_tree_add_item(tree, hf_ansi_801_desired_pilot_phase_resolution, tvb, offset, 3, ENC_BIG_ENDIAN);
335
0
  proto_tree_add_item(tree, hf_ansi_801_reserved_24_7, tvb, offset, 3, ENC_BIG_ENDIAN);
336
0
  offset += 3;
337
338
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
339
0
}
340
341
static void
342
for_req_loc_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
343
0
{
344
0
  uint32_t  saved_offset;
345
346
0
  SHORT_DATA_CHECK(len, 3);
347
348
0
  saved_offset = offset;
349
350
0
  proto_tree_add_item(tree, hf_ansi_801_pref_resp_qual, tvb, offset, 3, ENC_BIG_ENDIAN);
351
0
  proto_tree_add_item(tree, hf_ansi_801_num_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
352
0
  proto_tree_add_item(tree, hf_ansi_801_t_betw_fixes, tvb, offset, 3, ENC_BIG_ENDIAN);
353
0
  proto_tree_add_item(tree, hf_ansi_801_for_req_loc_height_information, tvb, offset, 3, ENC_BIG_ENDIAN);
354
0
  proto_tree_add_item(tree, hf_ansi_801_for_req_loc_clock_correction_for_gps_time, tvb, offset, 3, ENC_BIG_ENDIAN);
355
0
  proto_tree_add_item(tree, hf_ansi_801_for_req_loc_velocity_information, tvb, offset, 3, ENC_BIG_ENDIAN);
356
0
  proto_tree_add_item(tree, hf_ansi_801_reserved24_3, tvb, offset, 3, ENC_BIG_ENDIAN);
357
0
  offset += 3;
358
359
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
360
0
}
361
362
static void
363
for_req_time_off_meas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
364
0
{
365
0
  uint8_t oct;
366
0
  uint32_t  saved_offset;
367
368
0
  SHORT_DATA_CHECK(len, 1);
369
370
0
  saved_offset = offset;
371
372
0
  oct = tvb_get_uint8(tvb, offset);
373
374
0
  proto_tree_add_item(tree, hf_ansi_801_use_action_time_indicator, tvb, offset, 1, ENC_NA);
375
376
0
  if (oct & 0x80)
377
0
  {
378
0
    proto_tree_add_item(tree, hf_ansi_801_action_time, tvb, offset, 1, ENC_BIG_ENDIAN);
379
0
    proto_tree_add_item(tree, hf_ansi_801_reserved8_01, tvb, offset, 1, ENC_BIG_ENDIAN);
380
0
  }
381
0
  else
382
0
  {
383
0
    proto_tree_add_item(tree, hf_ansi_801_reserved8_7F, tvb, offset, 1, ENC_BIG_ENDIAN);
384
0
  }
385
0
  offset++;
386
387
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
388
0
}
389
390
static void
391
for_req_cancel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
392
0
{
393
0
  uint8_t      oct;
394
0
  uint32_t     saved_offset;
395
0
  const char *str = NULL;
396
397
0
  SHORT_DATA_CHECK(len, 1);
398
399
0
  saved_offset = offset;
400
401
0
  oct = tvb_get_uint8(tvb, offset);
402
403
0
  str = val_to_str_const((oct & 0xf0) >> 4, for_req_type_strings, "Reserved");
404
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_cancellation_type, tvb, offset, 1,
405
0
          oct, "(%u) %s", (oct & 0xf0) >> 4, str);
406
407
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_0F, tvb, offset, 1, ENC_BIG_ENDIAN);
408
0
  offset++;
409
410
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
411
0
}
412
413
static void
414
for_reject(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
415
0
{
416
0
  uint8_t      oct;
417
0
  uint32_t     saved_offset;
418
0
  const char *str = NULL;
419
420
0
  saved_offset = offset;
421
422
0
  SHORT_DATA_CHECK(len, 1);
423
424
0
  oct = tvb_get_uint8(tvb, offset);
425
0
  str = val_to_str_const((oct & 0xf0) >> 4, rev_req_type_strings, "Reserved");
426
427
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_reject_request_type, tvb, offset, 1, oct,
428
0
          "(%u) %s", (oct & 0xf0) >> 4, str);
429
430
0
  switch ((oct & 0x0e) >> 1)
431
0
  {
432
0
  case 0x00: str = "Capability not supported by the base station"; break;
433
0
  case 0x01: str = "Capability normally supported by the base station but temporarily not available or not enabled"; break;
434
0
  default: str = "Reserved"; break;
435
0
  }
436
437
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_reject_reason, tvb, offset, 1, oct, "%s", str);
438
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_01, tvb, offset, 1, ENC_BIG_ENDIAN);
439
0
  offset++;
440
441
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
442
0
}
443
444
static void
445
for_pr_bs_cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
446
0
{
447
0
  uint8_t oct;
448
0
  uint32_t  saved_offset;
449
450
0
  saved_offset = offset;
451
452
0
  SHORT_DATA_CHECK(len, 2);
453
454
0
  proto_tree_add_item(tree, hf_ansi_801_bs_ls_rev, tvb, offset, 1, ENC_BIG_ENDIAN);
455
0
  proto_tree_add_item(tree, hf_ansi_801_gps_capability_indicator, tvb, offset, 1, ENC_BIG_ENDIAN);
456
0
  proto_tree_add_item(tree, hf_ansi_801_afltc_id, tvb, offset, 1, ENC_BIG_ENDIAN);
457
0
  offset++;
458
459
0
  oct = tvb_get_uint8(tvb, offset);
460
0
  if (oct == 0x00)
461
0
  {
462
0
    proto_tree_add_uint_format(tree, hf_ansi_801_apdc_id, tvb, offset, 1, 0,
463
0
            "APDC_ID: Autonomous position determination capability indicator: None");
464
0
  }
465
0
  else
466
0
  {
467
0
    proto_tree_add_item(tree, hf_ansi_801_apdc_id, tvb, offset, 1, ENC_BIG_ENDIAN);
468
0
  }
469
470
0
  offset++;
471
472
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
473
0
}
474
475
static void
476
for_pr_gps_sense_ass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
477
0
{
478
0
  uint32_t  saved_offset;
479
480
0
  saved_offset = offset;
481
482
0
  SHORT_DATA_CHECK(len, 4);
483
484
0
  proto_tree_add_item(tree, hf_ansi_801_ref_bit_num, tvb, offset, 2, ENC_BIG_ENDIAN);
485
0
  proto_tree_add_item(tree, hf_ansi_801_num_dr_p, tvb, offset, 2, ENC_BIG_ENDIAN);
486
0
  offset += 2;
487
488
0
  proto_tree_add_item(tree, hf_ansi_801_dr_size, tvb, offset, 3, ENC_BIG_ENDIAN);
489
0
  offset++;
490
491
0
  proto_tree_add_item(tree, hf_ansi_801_part_num, tvb, offset, 2, ENC_BIG_ENDIAN);
492
0
  proto_tree_add_item(tree, hf_ansi_801_total_parts, tvb, offset, 2, ENC_BIG_ENDIAN);
493
0
  proto_tree_add_item(tree, hf_ansi_801_data_records, tvb, offset, 2, ENC_BIG_ENDIAN);
494
0
  offset++;
495
496
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
497
0
}
498
499
static void
500
for_pr_gps_almanac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
501
0
{
502
0
  uint32_t  saved_offset = offset;
503
0
  int * const fields[] = {
504
0
    &hf_ansi_801_num_sv_p32,
505
0
    &hf_ansi_801_week_num,
506
0
    &hf_ansi_801_toa,
507
0
    &hf_ansi_801_part_num32,
508
0
    &hf_ansi_801_total_parts32,
509
0
    NULL
510
0
  };
511
512
0
  SHORT_DATA_CHECK(len, 4);
513
514
0
    proto_tree_add_bitmask_list(tree, tvb, offset, 4, fields, ENC_BIG_ENDIAN);
515
0
  offset += 4;
516
517
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
518
0
}
519
520
static void
521
for_pr_gps_nav_msg_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
522
0
{
523
0
  uint32_t  saved_offset = offset;
524
0
  int * const fields[] = {
525
0
    &hf_ansi_801_num_sv_p16,
526
0
    &hf_ansi_801_part_num16,
527
0
    &hf_ansi_801_total_parts16,
528
0
    NULL
529
0
  };
530
531
0
  SHORT_DATA_CHECK(len, 2);
532
533
0
    proto_tree_add_bitmask_list(tree, tvb, offset, 2, fields, ENC_BIG_ENDIAN);
534
0
  offset += 2;
535
536
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
537
0
}
538
539
/*
540
 * shared for both forward/reverse directions
541
 */
542
static const true_false_string ansi_801_fix_type_vals = {
543
  "3D",
544
  "2D"
545
};
546
547
static void
548
pr_loc_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
549
0
{
550
0
  uint32_t     bit_offset, spare_bits;
551
0
  uint32_t     value;
552
0
  float        fl_value;
553
0
  uint32_t     saved_offset;
554
0
  uint64_t     fix_type, velocity_incl, clock_incl, height_incl;
555
0
  const char *str = NULL;
556
557
0
  SHORT_DATA_CHECK(len, 11);
558
0
  saved_offset = offset;
559
0
  bit_offset   = offset << 3;
560
561
  /* TIME_REF_CDMA */
562
0
  value = tvb_get_bits16(tvb, bit_offset, 14, ENC_BIG_ENDIAN);
563
0
  proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_time_ref_cdma, tvb, bit_offset, 14, value * 50,
564
0
                ENC_BIG_ENDIAN, "%u frames (0x%04x)", value * 50, value);
565
0
  bit_offset += 14;
566
567
  /* LAT */
568
0
  value = tvb_get_bits32(tvb, bit_offset, 25, ENC_BIG_ENDIAN);
569
0
  fl_value = (float)(-90.0 + ((float)value * 180 / 33554432));
570
0
  proto_tree_add_float_bits_format_value(tree, hf_ansi_801_lat, tvb, bit_offset, 25, fl_value, ENC_BIG_ENDIAN,
571
0
                 "%.5f degrees %s (0x%08x)", fabs(fl_value), fl_value < 0 ? "South" : "North", value);
572
0
  bit_offset += 25;
573
574
  /* LONG */
575
0
  value    = tvb_get_bits32(tvb, bit_offset, 26, ENC_BIG_ENDIAN);
576
0
  fl_value = (float)(-180.0 + ((float)value * 180 / 33554432));
577
0
  proto_tree_add_float_bits_format_value(tree, hf_ansi_801_long, tvb, bit_offset, 26, fl_value, ENC_BIG_ENDIAN,
578
0
                 "%.5f degrees %s (0x%08x)", fabs(fl_value), fl_value < 0 ? "West" : "East", value);
579
0
  bit_offset += 26;
580
581
  /* LOC_UNCRTNTY_ANG */
582
0
  value    = tvb_get_bits8(tvb, bit_offset, 4);
583
0
  fl_value = (float)(5.625 * value);
584
0
  proto_tree_add_float_bits_format_value(tree, hf_ansi_801_loc_uncrtnty_ang, tvb, bit_offset, 4, fl_value,
585
0
                 ENC_BIG_ENDIAN, "%.5f degrees (0x%02x)", fl_value, value);
586
0
  bit_offset += 4;
587
588
  /* LOC_UNCRTNTY_A */
589
0
  value = tvb_get_bits8(tvb, bit_offset, 5);
590
0
  switch (value)
591
0
  {
592
0
  case 0x1e: str = "> 12288.00 meters"; break;
593
0
  case 0x1f: str = "Not computable"; break;
594
0
  default:
595
0
    fl_value = (float)(0.5f * (1 << (value >> 1)));
596
0
    if (value & 0x01)
597
0
      fl_value *= 1.5f;
598
0
    str = wmem_strdup_printf(pinfo->pool, "%.2f meters", fl_value);
599
0
  }
600
0
  proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_loc_uncrtnty_a, tvb, bit_offset, 5, value,
601
0
                ENC_BIG_ENDIAN, "%s (0x%02x)", str, value);
602
0
  bit_offset += 5;
603
604
  /* LOC_UNCRTNTY_P */
605
0
  value = tvb_get_bits8(tvb, bit_offset, 5);
606
0
  switch (value)
607
0
  {
608
0
  case 0x1e: str = "> 12288.00 meters"; break;
609
0
  case 0x1f: str = "Not computable"; break;
610
0
  default:
611
0
    fl_value = (float)(0.5f * (1 << (value >> 1)));
612
0
    if (value & 0x01)
613
0
      fl_value *= 1.5f;
614
0
    str = wmem_strdup_printf(pinfo->pool, "%.2f meters", fl_value);
615
0
  }
616
0
  proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_loc_uncrtnty_p, tvb, bit_offset, 5, value,
617
0
                ENC_BIG_ENDIAN, "%s (0x%02x)", str, value);
618
0
  bit_offset += 5;
619
620
  /* FIX_TYPE */
621
0
  proto_tree_add_bits_ret_val(tree, hf_ansi_801_fix_type, tvb, bit_offset++, 1, &fix_type, ENC_BIG_ENDIAN);
622
623
  /* VELOCITY_INCL */
624
0
  proto_tree_add_bits_ret_val(tree, hf_ansi_801_velocity_incl, tvb, bit_offset++, 1, &velocity_incl, ENC_BIG_ENDIAN);
625
626
627
0
  if(velocity_incl)
628
0
  {
629
    /* VELOCITY_HOR */
630
0
    value = tvb_get_bits16(tvb, bit_offset, 9, ENC_BIG_ENDIAN);
631
0
    fl_value = (float)(0.25 * value);
632
0
    proto_tree_add_float_bits_format_value(tree, hf_ansi_801_velocity_hor, tvb, bit_offset, 9, fl_value,
633
0
                   ENC_BIG_ENDIAN, "%.2f m/s (0x%04x)", fl_value, value);
634
0
    bit_offset += 9;
635
636
    /* HEADING */
637
0
    value = tvb_get_bits16(tvb, bit_offset, 10, ENC_BIG_ENDIAN);
638
0
    fl_value = (float)value * 360 / 1024;
639
0
    proto_tree_add_float_bits_format_value(tree, hf_ansi_801_heading, tvb, bit_offset, 10, fl_value,
640
0
                   ENC_BIG_ENDIAN, "%.3f degrees (0x%04x)", fl_value, value);
641
0
    bit_offset += 10;
642
643
0
    if(fix_type)
644
0
    {
645
      /* VELOCITY_VER */
646
0
      value = tvb_get_bits8(tvb, bit_offset, 8);
647
0
      fl_value = (float)(-64 + 0.5 * value);
648
0
      proto_tree_add_float_bits_format_value(tree, hf_ansi_801_velocity_ver, tvb, bit_offset, 8, fl_value,
649
0
                     ENC_BIG_ENDIAN, "%.1f m/s (0x%02x)", fl_value, value);
650
0
      bit_offset += 8;
651
0
    }
652
0
  }
653
654
  /* CLOCK_INCL */
655
0
  proto_tree_add_bits_ret_val(tree, hf_ansi_801_clock_incl, tvb, bit_offset++, 1, &clock_incl, ENC_BIG_ENDIAN);
656
657
0
  if(clock_incl)
658
0
  {
659
    /* CLOCK_BIAS */
660
0
    value = tvb_get_bits32(tvb, bit_offset, 18, ENC_BIG_ENDIAN);
661
0
    proto_tree_add_int_bits_format_value(tree, hf_ansi_801_clock_bias, tvb, bit_offset, 18, (int32_t)value - 13000,
662
0
                 ENC_BIG_ENDIAN, "%d ns (0x%06x)", (int32_t)value - 13000, value);
663
0
    bit_offset += 18;
664
665
    /* CLOCK_DRIFT */
666
0
    value = tvb_get_bits16(tvb, bit_offset, 16, ENC_BIG_ENDIAN);
667
0
    proto_tree_add_int_bits_format_value(tree, hf_ansi_801_clock_drift, tvb, bit_offset, 16, (int16_t)value,
668
0
                 ENC_BIG_ENDIAN, "%d ppb (ns/s) (0x%04x)", (int16_t)value, value);
669
0
    bit_offset += 16;
670
0
  }
671
672
  /* HEIGHT_INCL */
673
0
  proto_tree_add_bits_ret_val(tree, hf_ansi_801_height_incl, tvb, bit_offset++, 1, &height_incl, ENC_BIG_ENDIAN);
674
675
0
  if(height_incl)
676
0
  {
677
    /* HEIGHT */
678
0
    value = tvb_get_bits16(tvb, bit_offset, 14, ENC_BIG_ENDIAN);
679
0
    proto_tree_add_int_bits_format_value(tree, hf_ansi_801_height, tvb, bit_offset, 14, (int32_t)value - 500,
680
0
                 ENC_BIG_ENDIAN, "%d m (0x%04x)", (int32_t)value - 500, value);
681
0
    bit_offset += 14;
682
683
    /* LOC_UNCRTNTY_V */
684
0
    value = tvb_get_bits8(tvb, bit_offset, 5);
685
0
    switch (value)
686
0
    {
687
0
    case 0x1e: str = "> 12288.00 meters"; break;
688
0
    case 0x1f: str = "Not computable"; break;
689
0
    default:
690
0
      fl_value = (float)(0.5f * (1 << (value >> 1)));
691
0
      if (value & 0x01)
692
0
        fl_value *= 1.5f;
693
0
      str = wmem_strdup_printf(pinfo->pool, "%.2f meters", fl_value);
694
0
    }
695
0
    proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_loc_uncrtnty_v, tvb, bit_offset, 5, value,
696
0
                  ENC_BIG_ENDIAN, "%s (0x%02x)", str, value);
697
0
    bit_offset += 5;
698
0
  }
699
700
0
  if(bit_offset & 0x07)
701
0
  {
702
0
    spare_bits = 8 - (bit_offset & 0x07);
703
0
    proto_tree_add_bits_item(tree, hf_ansi_801_reserved_bits, tvb, bit_offset, spare_bits, ENC_BIG_ENDIAN);
704
0
    bit_offset += spare_bits;
705
0
  }
706
707
0
  offset = bit_offset >> 3;
708
709
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
710
0
}
711
712
static void
713
for_pr_loc_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
714
0
{
715
0
  pr_loc_response(tvb, pinfo, tree, len, offset);
716
0
}
717
718
static void
719
for_pr_gps_sat_health(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
720
0
{
721
0
  uint32_t  bit_offset, spare_bits;
722
0
  uint32_t  i;
723
0
  uint32_t  saved_offset, num_bad_sv, bad_sv_prn_num;
724
0
  uint64_t  bad_sv_present;
725
726
0
  SHORT_DATA_CHECK(len, 1);
727
0
  saved_offset = offset;
728
0
  bit_offset   = offset << 3;
729
730
  /* BAD_SV_PRESENT */
731
0
  proto_tree_add_bits_ret_val(tree, hf_ansi_801_bad_sv_present, tvb, bit_offset++, 1, &bad_sv_present, ENC_BIG_ENDIAN);
732
733
0
  if (bad_sv_present)
734
0
  {
735
    /* NUM_BAD_SV */
736
0
    num_bad_sv = tvb_get_bits8(tvb, bit_offset, 4) + 1;
737
0
    proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_num_bad_sv, tvb, bit_offset, 4, num_bad_sv,
738
0
                  ENC_BIG_ENDIAN, "%u", num_bad_sv);
739
0
    bit_offset += 4;
740
741
0
    for (i=0; i < num_bad_sv; i++)
742
0
    {
743
      /* BAD_SV_PRN_NUM */
744
0
      bad_sv_prn_num = tvb_get_bits8(tvb, bit_offset, 5) + 1;
745
0
      proto_tree_add_uint_bits_format_value(tree, hf_ansi_801_bad_sv_prn_num, tvb, bit_offset, 5, bad_sv_prn_num,
746
0
                    ENC_BIG_ENDIAN, "%u", bad_sv_prn_num);
747
0
      bit_offset += 5;
748
0
    }
749
0
  }
750
751
0
  if(bit_offset & 0x07)
752
0
  {
753
0
    spare_bits = 8 - (bit_offset & 0x07);
754
0
    proto_tree_add_bits_item(tree, hf_ansi_801_reserved_bits, tvb, bit_offset, spare_bits, ENC_BIG_ENDIAN);
755
0
    bit_offset += spare_bits;
756
0
  }
757
758
0
  offset = bit_offset >> 3;
759
760
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
761
0
}
762
763
static void
764
rev_req_gps_acq_ass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
765
0
{
766
0
  uint32_t  saved_offset;
767
0
  uint32_t  bit_offset;
768
769
0
  SHORT_DATA_CHECK(len, 1);
770
0
  saved_offset = offset;
771
0
  bit_offset   = offset << 3;
772
773
0
  proto_tree_add_bits_item(tree, hf_ansi_801_dopp_req, tvb, bit_offset++, 1, ENC_BIG_ENDIAN);
774
0
  proto_tree_add_bits_item(tree, hf_ansi_801_add_dopp_req, tvb, bit_offset++, 1, ENC_BIG_ENDIAN);
775
0
  proto_tree_add_bits_item(tree, hf_ansi_801_code_ph_par_req, tvb, bit_offset++, 1, ENC_BIG_ENDIAN);
776
0
  proto_tree_add_bits_item(tree, hf_ansi_801_az_el_req, tvb, bit_offset++, 1, ENC_BIG_ENDIAN);
777
0
  proto_tree_add_bits_item(tree, hf_ansi_801_reserved_bits, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
778
0
  offset++;
779
780
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
781
0
}
782
783
static void
784
rev_req_gps_loc_ass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
785
0
{
786
0
  uint32_t saved_offset;
787
788
0
  SHORT_DATA_CHECK(len, 1);
789
790
0
  saved_offset = offset;
791
792
0
  proto_tree_add_item(tree, hf_ansi_801_coordinate_type_requested, tvb, offset, 1, ENC_NA);
793
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_7F, tvb, offset, 1, ENC_BIG_ENDIAN);
794
0
  offset++;
795
796
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
797
0
}
798
799
static void
800
rev_req_bs_alm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
801
0
{
802
0
  uint32_t saved_offset;
803
804
0
  SHORT_DATA_CHECK(len, 1);
805
806
0
  saved_offset = offset;
807
808
0
  proto_tree_add_item(tree, hf_ansi_801_extended_base_station_almanac, tvb, offset, 1, ENC_NA);
809
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_7F, tvb, offset, 1, ENC_BIG_ENDIAN);
810
0
  offset++;
811
812
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
813
0
}
814
815
static void
816
rev_req_gps_ephemeris(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
817
0
{
818
0
  uint32_t saved_offset;
819
820
0
  SHORT_DATA_CHECK(len, 1);
821
822
0
  saved_offset = offset;
823
824
0
  proto_tree_add_item(tree, hf_ansi_801_alpha_and_beta_parameters, tvb, offset, 1, ENC_NA);
825
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_7F, tvb, offset, 1, ENC_BIG_ENDIAN);
826
0
  offset++;
827
828
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
829
0
}
830
831
static void
832
rev_req_gps_nav_msg_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
833
0
{
834
0
  uint32_t saved_offset;
835
836
0
  SHORT_DATA_CHECK(len, 1);
837
838
0
  saved_offset = offset;
839
840
0
  proto_tree_add_item(tree, hf_ansi_801_subframes_4_and_5, tvb, offset, 1, ENC_NA);
841
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_7F, tvb, offset, 1, ENC_BIG_ENDIAN);
842
843
0
  offset++;
844
845
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
846
0
}
847
848
static void
849
rev_req_loc_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
850
0
{
851
0
  uint32_t saved_offset;
852
853
0
  SHORT_DATA_CHECK(len, 1);
854
855
0
  saved_offset = offset;
856
857
0
  proto_tree_add_item(tree, hf_ansi_801_rev_req_loc_height_information, tvb, offset, 1, ENC_NA);
858
0
  proto_tree_add_item(tree, hf_ansi_801_rev_req_loc_clock_correction_for_gps_time, tvb, offset, 1, ENC_NA);
859
0
  proto_tree_add_item(tree, hf_ansi_801_rev_req_loc_velocity_information, tvb, offset, 1, ENC_NA);
860
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_1F, tvb, offset, 1, ENC_BIG_ENDIAN);
861
0
  offset++;
862
863
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
864
0
}
865
866
static void
867
rev_req_gps_alm_correction(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
868
0
{
869
0
  uint32_t  saved_offset;
870
871
0
  SHORT_DATA_CHECK(len, 2);
872
873
0
  saved_offset = offset;
874
875
0
  proto_tree_add_item(tree, hf_ansi_801_time_of_almanac, tvb, offset, 1, ENC_NA);
876
877
0
  offset++;
878
0
  proto_tree_add_item(tree, hf_ansi_801_gps_week_number, tvb, offset, 1, ENC_NA);
879
880
0
  offset++;
881
882
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
883
0
}
884
885
static void
886
rev_reject(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
887
0
{
888
0
  uint8_t      oct;
889
0
  uint32_t     saved_offset;
890
0
  const char *str = NULL;
891
892
0
  saved_offset = offset;
893
894
0
  SHORT_DATA_CHECK(len, 1);
895
896
0
  oct = tvb_get_uint8(tvb, offset);
897
898
0
  str = val_to_str_const((oct & 0xf0) >> 4, for_req_type_strings, "Reserved");
899
900
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_reject_request_type, tvb, offset, 1, oct,
901
0
          "(%u) %s", (oct & 0xf0) >> 4, str);
902
903
0
  switch ((oct & 0x0e) >> 1)
904
0
  {
905
0
  case 0x00: str = "Capability not supported by the mobile station"; break;
906
0
  case 0x01: str = "Capability normally supported by the mobile station but temporarily not available or not enabled"; break;
907
0
  default: str = "Reserved"; break;
908
0
  }
909
910
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_reject_reason, tvb, offset, 1,
911
0
          oct, "%s", str);
912
913
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_01, tvb, offset, 1, ENC_BIG_ENDIAN);
914
0
  offset++;
915
916
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
917
0
}
918
919
static void
920
rev_pr_ms_information(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
921
0
{
922
0
  uint32_t     value;
923
0
  uint32_t     saved_offset;
924
0
  const char *str = NULL;
925
0
  proto_item* ti;
926
0
  proto_tree *gps_tree, *loc_tree;
927
928
0
  saved_offset = offset;
929
930
0
  SHORT_DATA_CHECK(len, 5);
931
932
0
  value = tvb_get_ntohs(tvb, offset);
933
934
0
  proto_tree_add_item(tree, hf_ansi_801_ms_ls_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
935
936
0
  proto_tree_add_item(tree, hf_ansi_801_ms_mode, tvb, offset, 2, ENC_BIG_ENDIAN);
937
938
0
  switch (value & 0x003f)
939
0
  {
940
0
  case 0x00: str = "Full Chip Measurement Capability"; break;
941
0
  case 0x01: str = "Half Chip Measurement Capability"; break;
942
0
  case 0x02: str = "Quarter Chip Measurement Capability"; break;
943
0
  case 0x03: str = "Eighth Chip Measurement Capability"; break;
944
0
  case 0x04: str = "One Sixteenth Chip Measurement Capability"; break;
945
0
  default: str = "Reserved"; break;
946
0
  }
947
948
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_pilot_ph_cap, tvb, offset, 2,
949
0
          value, "(%u) %s", value & 0x3f, str);
950
0
  offset += 2;
951
952
0
  ti = proto_tree_add_item(tree, hf_ansi_801_gps_acq_cap, tvb, offset, 3, ENC_BIG_ENDIAN);
953
0
  gps_tree = proto_item_add_subtree(ti, ett_gps);
954
955
0
  proto_tree_add_item(gps_tree, hf_ansi_801_reserved_24_F80000, tvb, offset, 3, ENC_BIG_ENDIAN);
956
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_autonomous_acquisition_capable, tvb, offset, 3, ENC_BIG_ENDIAN);
957
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_almanac_correction, tvb, offset, 3, ENC_BIG_ENDIAN);
958
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_navigation_message_bits, tvb, offset, 3, ENC_BIG_ENDIAN);
959
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_ephemeris, tvb, offset, 3, ENC_BIG_ENDIAN);
960
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_almanac, tvb, offset, 3, ENC_BIG_ENDIAN);
961
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_sensitivity_assistance, tvb, offset, 3, ENC_BIG_ENDIAN);
962
0
  proto_tree_add_item(gps_tree, hf_ansi_801_gps_acquisition_assistance, tvb, offset, 3, ENC_BIG_ENDIAN);
963
964
0
  ti = proto_tree_add_item(tree, hf_ansi_801_loc_calc_cap, tvb, offset, 3, ENC_BIG_ENDIAN);
965
0
  loc_tree = proto_item_add_subtree(ti, ett_loc);
966
967
0
  proto_tree_add_item(loc_tree, hf_ansi_801_pre_programmed_location, tvb, offset, 3, ENC_BIG_ENDIAN);
968
0
  proto_tree_add_item(loc_tree, hf_ansi_801_reserved_24_700, tvb, offset, 3, ENC_BIG_ENDIAN);
969
0
  proto_tree_add_item(loc_tree, hf_ansi_801_hybrid_gps_and_aflt_lcc, tvb, offset, 3, ENC_BIG_ENDIAN);
970
0
  proto_tree_add_item(loc_tree, hf_ansi_801_autonomous_location_calculation_capable, tvb, offset, 3, ENC_BIG_ENDIAN);
971
0
  proto_tree_add_item(loc_tree, hf_ansi_801_lcc_using_gps_almanac_correction, tvb, offset, 3, ENC_BIG_ENDIAN);
972
0
  proto_tree_add_item(loc_tree, hf_ansi_801_lcc_using_gps_ephemeris_assistance, tvb, offset, 3, ENC_BIG_ENDIAN);
973
0
  proto_tree_add_item(loc_tree, hf_ansi_801_lcc_using_gps_almanac_assistance, tvb, offset, 3, ENC_BIG_ENDIAN);
974
0
  proto_tree_add_item(loc_tree, hf_ansi_801_aflt_lcc, tvb, offset, 3, ENC_BIG_ENDIAN);
975
0
  proto_tree_add_item(loc_tree, hf_ansi_801_lcc_using_location_assistance_cartesian, tvb, offset, 3, ENC_BIG_ENDIAN);
976
0
  proto_tree_add_item(loc_tree, hf_ansi_801_lcc_capable_using_location_assistance_spherical, tvb, offset, 3, ENC_BIG_ENDIAN);
977
0
  offset += 3;
978
979
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
980
0
}
981
982
static void
983
rev_pr_loc_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
984
0
{
985
0
  pr_loc_response(tvb, pinfo, tree, len, offset);
986
0
}
987
988
static void
989
rev_pr_time_off_meas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
990
0
{
991
0
  uint32_t  saved_offset;
992
993
0
  saved_offset = offset;
994
995
0
  SHORT_DATA_CHECK(len, 6);
996
997
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_time_ref_ms, tvb, offset, 3, tvb_get_ntoh24(tvb, offset),
998
0
          "The time of validity of the parameters reported in this response element.");
999
0
  offset += 3;
1000
1001
0
  proto_tree_add_item(tree, hf_ansi_801_ref_pn, tvb, offset, 3, ENC_BIG_ENDIAN);
1002
0
  proto_tree_add_item(tree, hf_ansi_801_mob_sys_t_offset, tvb, offset, 3, ENC_BIG_ENDIAN);
1003
0
  proto_tree_add_item(tree, hf_ansi_801_reserved24_1, tvb, offset, 3, ENC_BIG_ENDIAN);
1004
0
  offset += 3;
1005
1006
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1007
0
}
1008
1009
static void
1010
rev_pr_can_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset)
1011
0
{
1012
0
  uint8_t      oct;
1013
0
  uint32_t     saved_offset;
1014
0
  const char *str;
1015
1016
0
  saved_offset = offset;
1017
1018
0
  SHORT_DATA_CHECK(len, 1);
1019
1020
0
  oct = tvb_get_uint8(tvb, offset);
1021
1022
0
  str = val_to_str_const((oct & 0xf0) >> 4, for_req_type_strings, "Reserved");
1023
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_cancellation_type, tvb, offset, 1, oct,
1024
0
          "(%u) %s", (oct & 0xf0) >> 4, str);
1025
1026
0
  proto_tree_add_item(tree, hf_ansi_801_no_outstanding_request_element, tvb, offset, 1, ENC_NA);
1027
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_07, tvb, offset, 1, ENC_BIG_ENDIAN);
1028
0
  offset++;
1029
1030
0
  EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
1031
0
}
1032
1033
static void (* const for_req_type_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset) = {
1034
  NULL, /* Reserved */
1035
  NULL, /* no data */ /* Request MS Information */
1036
  NULL, /* no data */ /* Request Autonomous Measurement Weighting Factors */
1037
  for_req_pseudo_meas,  /* Request Pseudorange Measurement */
1038
  for_req_pilot_ph_meas,  /* Request Pilot Phase Measurement */
1039
  for_req_loc_response, /* Request Location Response */
1040
  for_req_time_off_meas,  /* Request Time Offset Measurement */
1041
  for_req_cancel,   /* Request Cancellation */
1042
  NULL, /* NONE */
1043
};
1044
1045
static void (* const for_rsp_type_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset) = {
1046
  for_reject,              /* Reject */
1047
  for_pr_bs_cap,           /* Provide BS Capabilities */
1048
  NULL,                    /* Provide GPS Acquisition Assistance */
1049
  NULL,                    /* Provide GPS Location Assistance Spherical Coordinates */
1050
  NULL,                    /* Provide GPS Location Assistance Cartesian Coordinates */
1051
  for_pr_gps_sense_ass,    /* Provide GPS Sensitivity Assistance */
1052
  NULL,                    /* Provide Base Station Almanac */
1053
  for_pr_gps_almanac,      /* Provide GPS Almanac */
1054
  NULL,                    /* Provide GPS Ephemeris */
1055
  for_pr_gps_nav_msg_bits, /* Provide GPS Navigation Message Bits */
1056
  for_pr_loc_response,     /* Provide Location Response */
1057
  NULL,                    /* Provide GPS Almanac Correction */
1058
  for_pr_gps_sat_health,   /* Provide GPS Satellite Health Information */
1059
  NULL,                    /* NONE */
1060
};
1061
1062
static void (* const rev_req_type_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset) = {
1063
  NULL, /* Reserved */
1064
  NULL,   /* no data */   /* Request BS Capabilities */
1065
  rev_req_gps_acq_ass,    /* Request GPS Acquisition Assistance */
1066
  rev_req_gps_loc_ass,    /* Request GPS Location Assistance */
1067
  NULL, /* Reserved */
1068
  NULL,   /* no data */   /* Request GPS Sensitivity Assistance */
1069
  rev_req_bs_alm,     /* Request Base Station Almanac */
1070
  NULL,   /* no data */   /* Request GPS Almanac */
1071
  rev_req_gps_ephemeris,    /* Request GPS Ephemeris */
1072
  rev_req_gps_nav_msg_bits, /* Request GPS Navigation Message Bits */
1073
  rev_req_loc_response,   /* Request Location Response */
1074
  rev_req_gps_alm_correction, /* Request GPS Almanac Correction */
1075
  NULL,   /* no data */   /* Request GPS Satellite Health Information */
1076
  NULL, /* NONE */
1077
};
1078
1079
static void (* const rev_rsp_type_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned len, uint32_t offset) = {
1080
  rev_reject,            /* Reject */
1081
  rev_pr_ms_information, /* Provide MS Information */
1082
  NULL,                  /* Provide Autonomous Measurement Weighting Factors */
1083
  NULL,                  /* Provide Pseudorange Measurement */
1084
  NULL,                  /* Provide Pilot Phase Measurement */
1085
  rev_pr_loc_response,   /* Provide Location Response */
1086
  rev_pr_time_off_meas,  /* Provide Time Offset Measurement */
1087
  rev_pr_can_ack,        /* Provide Cancellation Acknowledgement */
1088
  NULL,                  /* NONE */
1089
};
1090
1091
static void
1092
for_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t *offset_p, uint8_t pd_msg_type)
1093
0
{
1094
0
  uint32_t     offset;
1095
0
  uint8_t      oct;
1096
0
  const char *str = NULL;
1097
0
  int          idx;
1098
0
  proto_tree  *subtree;
1099
0
  proto_item  *item;
1100
1101
0
  offset = *offset_p;
1102
0
  oct    = tvb_get_uint8(tvb, offset);
1103
1104
0
  if (pd_msg_type == 0x00)
1105
0
  {
1106
0
    proto_tree_add_item(tree, hf_ansi_801_reserved8_F0, tvb, offset, 1, ENC_BIG_ENDIAN);
1107
1108
0
    str = try_val_to_str_idx(oct & 0x0f, for_req_type_strings, &idx);
1109
0
    if (str == NULL)
1110
0
    {
1111
0
      return;
1112
0
    }
1113
1114
0
    item = proto_tree_add_uint_format_value(tree, hf_ansi_801_for_req_type, tvb, offset, 1,
1115
0
              oct & 0x0f, "%s (%u)", str, oct & 0x0f);
1116
0
  }
1117
0
  else
1118
0
  {
1119
    /* TBD */
1120
    /*
1121
     * It is unclear from TIA-801-A how this was meant to be decoded.
1122
     * Are the elements supposed to be byte aligned?
1123
     */
1124
0
    return;
1125
0
  }
1126
1127
0
  subtree = proto_item_add_subtree(item, ett_for_req_type[idx]);
1128
1129
0
  offset++;
1130
0
  oct = tvb_get_uint8(tvb, offset);
1131
1132
0
  proto_tree_add_item(subtree, hf_ansi_801_for_request_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1133
0
  offset++;
1134
1135
0
  if (oct > 0)
1136
0
  {
1137
0
    if (for_req_type_fcn[idx] != NULL)
1138
0
    {
1139
0
      (*for_req_type_fcn[idx])(tvb, pinfo, subtree, oct, offset);
1140
0
    }
1141
0
    else
1142
0
    {
1143
0
      proto_tree_add_item(subtree, hf_ansi_801_data, tvb, offset, oct, ENC_NA);
1144
0
    }
1145
0
  }
1146
1147
0
  *offset_p = offset + oct;
1148
0
}
1149
1150
static void
1151
for_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t *offset_p)
1152
0
{
1153
0
  uint32_t     offset;
1154
0
  uint8_t      oct;
1155
0
  const char *str = NULL;
1156
0
  int          idx;
1157
0
  proto_tree  *subtree;
1158
0
  proto_item  *item;
1159
1160
0
  offset = *offset_p;
1161
0
  oct    = tvb_get_uint8(tvb, offset);
1162
1163
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_E0, tvb, offset, 1, ENC_BIG_ENDIAN);
1164
0
  proto_tree_add_item(tree, hf_ansi_801_unsolicited_response_indicator, tvb, offset, 1, ENC_NA);
1165
1166
0
  str = try_val_to_str_idx(oct & 0x0f, for_rsp_type_strings, &idx);
1167
1168
0
  if (str == NULL)
1169
0
  {
1170
0
    return;
1171
0
  }
1172
1173
0
  item = proto_tree_add_uint_format_value(tree, hf_ansi_801_for_rsp_type, tvb, offset, 1,
1174
0
            oct & 0x0f, "%s (%u)", str, oct & 0x0f);
1175
0
  subtree = proto_item_add_subtree(item, ett_for_rsp_type[idx]);
1176
1177
0
  offset++;
1178
0
  oct = tvb_get_uint8(tvb, offset);
1179
1180
0
  proto_tree_add_item(subtree, hf_ansi_801_for_response_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1181
1182
0
  offset++;
1183
1184
0
  if (for_rsp_type_fcn[idx] != NULL)
1185
0
  {
1186
0
    (*for_rsp_type_fcn[idx])(tvb, pinfo, subtree, oct, offset);
1187
0
  }
1188
0
  else
1189
0
  {
1190
0
    proto_tree_add_item(subtree, hf_ansi_801_data, tvb, offset, oct, ENC_NA);
1191
0
  }
1192
1193
0
  *offset_p = offset + oct;
1194
0
}
1195
1196
static void
1197
rev_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t *offset_p, uint8_t pd_msg_type)
1198
0
{
1199
0
  uint32_t     offset;
1200
0
  uint8_t      oct;
1201
0
  const char *str = NULL;
1202
0
  int          idx;
1203
0
  proto_tree  *subtree;
1204
0
  proto_item  *item;
1205
1206
0
  offset = *offset_p;
1207
0
  oct    = tvb_get_uint8(tvb, offset);
1208
1209
0
  if (pd_msg_type == 0x00)
1210
0
  {
1211
0
    proto_tree_add_item(tree, hf_ansi_801_reserved8_F0, tvb, offset, 1, ENC_BIG_ENDIAN);
1212
1213
0
    str = try_val_to_str_idx(oct & 0x0f, rev_req_type_strings, &idx);
1214
0
    if (str == NULL)
1215
0
    {
1216
0
      return;
1217
0
    }
1218
1219
0
    item = proto_tree_add_uint_format_value(tree, hf_ansi_801_rev_req_type, tvb, offset, 1,
1220
0
              oct & 0x0f, "%s (%u)", str, oct & 0x0f);
1221
0
  }
1222
0
  else
1223
0
  {
1224
    /* TBD */
1225
    /*
1226
     * It is unclear from TIA-801-A how this was meant to be decoded.
1227
     * Are the elements supposed to be byte aligned?
1228
     */
1229
0
    return;
1230
0
  }
1231
1232
0
  subtree = proto_item_add_subtree(item, ett_rev_req_type[idx]);
1233
1234
0
  offset++;
1235
0
  oct = tvb_get_uint8(tvb, offset);
1236
1237
0
  proto_tree_add_item(subtree, hf_ansi_801_rev_request_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1238
1239
0
  offset++;
1240
1241
0
  if (rev_req_type_fcn[idx] != NULL)
1242
0
  {
1243
0
    (*rev_req_type_fcn[idx])(tvb, pinfo, subtree, oct, offset);
1244
0
  }
1245
0
  else
1246
0
  {
1247
0
    proto_tree_add_item(subtree, hf_ansi_801_data, tvb, offset, oct, ENC_NA);
1248
0
  }
1249
1250
0
  *offset_p = offset + oct;
1251
0
}
1252
1253
static void
1254
rev_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t *offset_p)
1255
0
{
1256
0
  uint32_t     offset;
1257
0
  uint8_t      oct;
1258
0
  const char *str = NULL;
1259
0
  int          idx;
1260
0
  proto_tree  *subtree;
1261
0
  proto_item  *item;
1262
1263
0
  offset = *offset_p;
1264
0
  oct    = tvb_get_uint8(tvb, offset);
1265
1266
0
  proto_tree_add_item(tree, hf_ansi_801_reserved8_E0, tvb, offset, 1, ENC_BIG_ENDIAN);
1267
0
  proto_tree_add_item(tree, hf_ansi_801_unsolicited_response_indicator, tvb, offset, 1, ENC_NA);
1268
1269
0
  str = try_val_to_str_idx(oct & 0x0f, rev_rsp_type_strings, &idx);
1270
1271
0
  if (str == NULL)
1272
0
  {
1273
0
    return;
1274
0
  }
1275
1276
0
  item = proto_tree_add_uint_format_value(tree, hf_ansi_801_rev_rsp_type, tvb, offset, 1,
1277
0
            oct & 0x0f, "%s (%u)", str, oct & 0x0f);
1278
0
  subtree = proto_item_add_subtree(item, ett_rev_rsp_type[idx]);
1279
0
  offset++;
1280
1281
0
  oct = tvb_get_uint8(tvb, offset);
1282
1283
0
  proto_tree_add_item(subtree, hf_ansi_801_rev_response_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1284
1285
0
  offset++;
1286
1287
0
  if (rev_rsp_type_fcn[idx] != NULL)
1288
0
  {
1289
0
    (*rev_rsp_type_fcn[idx])(tvb, pinfo, subtree, oct, offset);
1290
0
  }
1291
0
  else
1292
0
  {
1293
0
    proto_tree_add_item(subtree, hf_ansi_801_data, tvb, offset, oct, ENC_NA);
1294
0
  }
1295
1296
0
  *offset_p = offset + oct;
1297
0
}
1298
1299
static void
1300
dissect_ansi_801_for_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1301
0
{
1302
0
  uint32_t     value;
1303
0
  uint32_t     offset;
1304
0
  uint8_t      oct, num_req, num_rsp, pd_msg_type;
1305
0
  unsigned     rem_len;
1306
0
  const char *str = NULL;
1307
0
  proto_item  *hidden_item;
1308
1309
0
  offset = 0;
1310
1311
0
  proto_tree_add_item(tree, hf_ansi_801_session_start, tvb, offset, 1, ENC_NA);
1312
0
  proto_tree_add_item(tree, hf_ansi_801_session_end, tvb, offset, 1, ENC_NA);
1313
0
  proto_tree_add_item(tree, hf_ansi_801_session_source, tvb, offset, 1, ENC_NA);
1314
0
  proto_tree_add_item(tree, hf_ansi_801_for_sess_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
1315
1316
0
  hidden_item = proto_tree_add_item(tree, hf_ansi_801_sess_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
1317
0
  proto_item_set_hidden(hidden_item);
1318
1319
0
  offset++;
1320
0
  oct = tvb_get_uint8(tvb, offset);
1321
0
  pd_msg_type = oct;
1322
1323
0
  switch (pd_msg_type)
1324
0
  {
1325
0
  case 0x00: str = "Position Determination Data Message"; break;
1326
0
  case 0x01: str = "Position Determination Data Message"; break;
1327
0
  case 0xff: str = "Reserved"; break;
1328
0
  default:
1329
0
    if (pd_msg_type < 0xc0)
1330
0
    {
1331
0
      str = "Reserved for future standardization";
1332
0
    }
1333
0
    else
1334
0
    {
1335
0
      str = "Available for manufacturer-specific Position Determination "
1336
0
          "Data Message definition as specified in TSB-58";
1337
0
    }
1338
0
    break;
1339
0
  }
1340
1341
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_pd_message_type, tvb, offset, 1, pd_msg_type,
1342
0
          "%s (%u)", str, pd_msg_type);
1343
1344
0
  offset++;
1345
1346
0
  if ((pd_msg_type != 0x00) &&
1347
0
      (pd_msg_type != 0x01))
1348
0
  {
1349
0
    proto_tree_add_item(tree, hf_ansi_801_proprietary_data, tvb, offset, -1, ENC_NA);
1350
0
    return;
1351
0
  }
1352
1353
0
  if (pd_msg_type == 0x01)
1354
0
  {
1355
0
    value = tvb_get_ntohs(tvb, offset);
1356
1357
0
    proto_tree_add_item(tree, hf_ansi_801_pd_message_len, tvb, offset, 2, ENC_BIG_ENDIAN);
1358
0
    proto_tree_add_item(tree, hf_ansi_801_regulatory_services_indicator, tvb, offset, 2, ENC_BIG_ENDIAN);
1359
1360
0
    num_req = value & 0x000f;
1361
1362
0
    proto_tree_add_item(tree, hf_ansi_801_for_message_number_requests16, tvb, offset, 2, ENC_BIG_ENDIAN);
1363
0
    offset += 2;
1364
1365
0
    oct = tvb_get_uint8(tvb, offset);
1366
0
    num_rsp = oct & 0xf0;
1367
1368
0
    proto_tree_add_item(tree, hf_ansi_801_for_message_number_responsesF0, tvb, offset, 1, ENC_BIG_ENDIAN);
1369
0
    offset++;
1370
0
  }
1371
0
  else
1372
0
  {
1373
0
    oct = tvb_get_uint8(tvb, offset);
1374
1375
0
    num_req = (oct & 0xf0) >> 4;
1376
0
    num_rsp = oct & 0x0f;
1377
1378
0
    proto_tree_add_item(tree, hf_ansi_801_for_message_number_requests8, tvb, offset, 1, ENC_BIG_ENDIAN);
1379
0
    proto_tree_add_item(tree, hf_ansi_801_for_message_number_responses0F, tvb, offset, 1, ENC_BIG_ENDIAN);
1380
0
  }
1381
1382
0
  offset++;
1383
0
  rem_len = tvb_reported_length_remaining(tvb, offset);
1384
1385
0
  while ((num_req > 0) &&
1386
0
         (rem_len >= 2))
1387
0
  {
1388
0
    for_request(tvb, pinfo, tree, &offset, pd_msg_type);
1389
1390
0
    rem_len = tvb_reported_length_remaining(tvb, offset);
1391
0
    num_req--;
1392
0
  }
1393
1394
0
  if (num_req != 0)
1395
0
  {
1396
0
    proto_tree_add_expert_remaining(tree, pinfo, &ei_ansi_801_short_data, tvb, offset);
1397
0
    return;
1398
0
  }
1399
1400
0
  while ((num_rsp > 0) &&
1401
0
         (rem_len >= 2))
1402
0
  {
1403
0
    for_response(tvb, pinfo, tree, &offset);
1404
1405
0
    rem_len = tvb_reported_length_remaining(tvb, offset);
1406
0
    num_rsp--;
1407
0
  }
1408
1409
0
  if (num_rsp != 0)
1410
0
  {
1411
0
    proto_tree_add_expert_remaining(tree, pinfo, &ei_ansi_801_short_data, tvb, offset);
1412
0
    return;
1413
0
  }
1414
1415
0
  if (rem_len > 0)
1416
0
  {
1417
0
    proto_tree_add_expert(tree, pinfo, &ei_ansi_801_extraneous_data, tvb, offset, rem_len);
1418
0
  }
1419
0
}
1420
1421
static void
1422
dissect_ansi_801_rev_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1423
0
{
1424
0
  uint32_t     value;
1425
0
  uint32_t     offset;
1426
0
  uint8_t      oct, num_req, num_rsp, pd_msg_type;
1427
0
  unsigned     rem_len;
1428
0
  const char *str = NULL;
1429
0
  proto_item  *hidden_item;
1430
1431
0
  offset = 0;
1432
1433
0
  proto_tree_add_item(tree, hf_ansi_801_session_start, tvb, offset, 1, ENC_NA);
1434
0
  proto_tree_add_item(tree, hf_ansi_801_session_end, tvb, offset, 1, ENC_NA);
1435
0
  proto_tree_add_item(tree, hf_ansi_801_session_source, tvb, offset, 1, ENC_NA);
1436
0
  proto_tree_add_item(tree, hf_ansi_801_rev_sess_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
1437
1438
0
  hidden_item = proto_tree_add_item(tree, hf_ansi_801_sess_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
1439
0
  proto_item_set_hidden(hidden_item);
1440
1441
0
  offset++;
1442
0
  oct = tvb_get_uint8(tvb, offset);
1443
0
  pd_msg_type = oct;
1444
1445
0
  switch (pd_msg_type)
1446
0
  {
1447
0
  case 0x00: str = "Position Determination Data Message"; break;
1448
0
  case 0x01: str = "Position Determination Data Message"; break;
1449
0
  case 0xff: str = "Reserved"; break;
1450
0
  default:
1451
0
    if (pd_msg_type < 0xc0)
1452
0
    {
1453
0
      str = "Reserved for future standardization";
1454
0
    }
1455
0
    else
1456
0
    {
1457
0
      str = "Available for manufacturer-specific Position Determination "
1458
0
        "Data Message definition as specified in TSB-58";
1459
0
    }
1460
0
    break;
1461
0
  }
1462
1463
0
  proto_tree_add_uint_format_value(tree, hf_ansi_801_pd_message_type, tvb, offset, 1, pd_msg_type,
1464
0
          "%s (%u)", str, pd_msg_type);
1465
0
  offset++;
1466
1467
0
  if ((pd_msg_type != 0x00) &&
1468
0
      (pd_msg_type != 0x01))
1469
0
  {
1470
0
    proto_tree_add_item(tree, hf_ansi_801_proprietary_data, tvb, offset, -1, ENC_NA);
1471
0
    return;
1472
0
  }
1473
1474
0
  if (pd_msg_type == 0x01)
1475
0
  {
1476
0
    value = tvb_get_ntohs(tvb, offset);
1477
1478
0
    proto_tree_add_item(tree, hf_ansi_801_pd_message_len, tvb, offset, 2, ENC_BIG_ENDIAN);
1479
0
    proto_tree_add_item(tree, hf_ansi_801_regulatory_services_indicator, tvb, offset, 2, ENC_BIG_ENDIAN);
1480
1481
0
    num_req = value & 0x000f;
1482
1483
0
    proto_tree_add_item(tree, hf_ansi_801_rev_message_number_requests16, tvb, offset, 2, ENC_BIG_ENDIAN);
1484
0
    offset += 2;
1485
1486
0
    oct = tvb_get_uint8(tvb, offset);
1487
0
    num_rsp = oct & 0xf0;
1488
1489
0
    proto_tree_add_item(tree, hf_ansi_801_rev_message_number_responsesF0, tvb, offset, 1, ENC_BIG_ENDIAN);
1490
0
    offset++;
1491
0
  }
1492
0
  else
1493
0
  {
1494
0
    oct = tvb_get_uint8(tvb, offset);
1495
1496
0
    num_req = (oct & 0xf0) >> 4;
1497
0
    num_rsp = oct & 0x0f;
1498
1499
0
    proto_tree_add_item(tree, hf_ansi_801_rev_message_number_requests8, tvb, offset, 1, ENC_BIG_ENDIAN);
1500
0
    proto_tree_add_item(tree, hf_ansi_801_rev_message_number_responses0F, tvb, offset, 1, ENC_BIG_ENDIAN);
1501
0
    offset++;
1502
0
  }
1503
1504
0
  rem_len = tvb_reported_length_remaining(tvb, offset);
1505
1506
0
  while ((num_req > 0) &&
1507
0
         (rem_len >= 2))
1508
0
  {
1509
0
    rev_request(tvb, pinfo, tree, &offset, pd_msg_type);
1510
1511
0
    rem_len = tvb_reported_length_remaining(tvb, offset);
1512
0
    num_req--;
1513
0
  }
1514
1515
0
  if (num_req != 0)
1516
0
  {
1517
0
    proto_tree_add_expert_remaining(tree, pinfo, &ei_ansi_801_short_data, tvb, offset);
1518
0
    return;
1519
0
  }
1520
1521
0
  while ((num_rsp > 0) &&
1522
0
         (rem_len >= 2))
1523
0
  {
1524
0
    rev_response(tvb, pinfo, tree, &offset);
1525
1526
0
    rem_len = tvb_reported_length_remaining(tvb, offset);
1527
0
    num_rsp--;
1528
0
  }
1529
1530
0
  if (num_rsp != 0)
1531
0
  {
1532
0
    proto_tree_add_expert_remaining(tree, pinfo, &ei_ansi_801_short_data, tvb, offset);
1533
0
    return;
1534
0
  }
1535
1536
0
  if (rem_len > 0)
1537
0
  {
1538
0
    proto_tree_add_expert(tree, pinfo, &ei_ansi_801_extraneous_data, tvb, offset, rem_len);
1539
0
  }
1540
0
}
1541
1542
static int
1543
dissect_ansi_801(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1544
0
{
1545
0
  proto_item *ansi_801_item;
1546
0
  proto_tree *ansi_801_tree = NULL;
1547
1548
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IS-801");
1549
1550
  /* In the interest of speed, if "tree" is NULL, don't do any work not
1551
   * necessary to generate protocol tree items.
1552
   */
1553
0
  if (tree)
1554
0
  {
1555
    /*
1556
     * create the ansi_801 protocol tree
1557
     */
1558
0
    ansi_801_item =
1559
0
      proto_tree_add_protocol_format(tree, proto_ansi_801, tvb, 0, -1,
1560
0
                   "ANSI IS-801 (Location Services (PLD)) %s Link",
1561
0
                   (pinfo->match_uint == ANSI_801_FORWARD) ? "Forward" : "Reverse");
1562
1563
0
    ansi_801_tree =
1564
0
      proto_item_add_subtree(ansi_801_item, ett_ansi_801);
1565
1566
0
    if (pinfo->match_uint == ANSI_801_FORWARD)
1567
0
    {
1568
0
      dissect_ansi_801_for_message(tvb, pinfo, ansi_801_tree);
1569
0
    }
1570
0
    else
1571
0
    {
1572
0
      dissect_ansi_801_rev_message(tvb, pinfo, ansi_801_tree);
1573
0
    }
1574
0
  }
1575
0
  return tvb_captured_length(tvb);
1576
0
}
1577
1578
1579
/* Register the protocol with Wireshark */
1580
void
1581
proto_register_ansi_801(void)
1582
14
{
1583
14
  unsigned i;
1584
14
  int   last_offset;
1585
1586
  /* Setup list of header fields */
1587
14
  static hf_register_info hf[] = {
1588
14
    { &hf_ansi_801_for_req_type,
1589
14
      { "Forward Request Type", "ansi_801.for_req_type",
1590
14
        FT_UINT8, BASE_DEC, NULL, 0,
1591
14
        NULL, HFILL }
1592
14
    },
1593
14
    { &hf_ansi_801_for_rsp_type,
1594
14
      { "Forward Response Type", "ansi_801.for_rsp_type",
1595
14
        FT_UINT8, BASE_DEC, NULL, 0,
1596
14
        NULL, HFILL }
1597
14
    },
1598
14
    { &hf_ansi_801_rev_req_type,
1599
14
      { "Reverse Request Type", "ansi_801.rev_req_type",
1600
14
        FT_UINT8, BASE_DEC, NULL, 0,
1601
14
        NULL, HFILL }
1602
14
    },
1603
14
    { &hf_ansi_801_rev_rsp_type,
1604
14
      { "Reverse Response Type", "ansi_801.rev_rsp_type",
1605
14
        FT_UINT8, BASE_DEC, NULL, 0,
1606
14
        NULL, HFILL }
1607
14
    },
1608
14
    { &hf_ansi_801_for_sess_tag,
1609
14
      { "Forward Session Tag", "ansi_801.for_sess_tag",
1610
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1611
14
        NULL, HFILL }
1612
14
    },
1613
14
    { &hf_ansi_801_rev_sess_tag,
1614
14
      { "Reverse Session Tag", "ansi_801.rev_sess_tag",
1615
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1616
14
        NULL, HFILL }
1617
14
    },
1618
14
    { &hf_ansi_801_sess_tag,
1619
14
      { "Session Tag", "ansi_801.sess_tag",
1620
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1621
14
        NULL, HFILL }
1622
14
    },
1623
14
    { &hf_ansi_801_time_ref_cdma,
1624
14
      { "CDMA system time at the time the solution is valid (TIME_REF_CDMA)", "ansi_801.time_ref_cdma",
1625
14
        FT_UINT32, BASE_DEC, NULL, 0x00,
1626
14
        NULL, HFILL }
1627
14
    },
1628
14
    { &hf_ansi_801_lat,
1629
14
      { "Latitude (LAT)", "ansi_801.lat",
1630
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1631
14
        NULL, HFILL }
1632
14
    },
1633
14
    { &hf_ansi_801_long,
1634
14
      { "Longitude (LONG)", "ansi_801.long",
1635
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1636
14
        NULL, HFILL }
1637
14
    },
1638
14
    { &hf_ansi_801_loc_uncrtnty_ang,
1639
14
      { "Angle of axis with respect to True North for pos uncertainty (LOC_UNCRTNTY_ANG)", "ansi_801.loc_uncrtnty_ang",
1640
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1641
14
        NULL, HFILL }
1642
14
    },
1643
14
    { &hf_ansi_801_loc_uncrtnty_a,
1644
14
      { "Std dev of axis along angle specified for pos uncertainty (LOC_UNCRTNTY_A)", "ansi_801.loc_uncrtnty_a",
1645
14
        FT_UINT8, BASE_DEC, NULL, 0x00,
1646
14
        NULL, HFILL }
1647
14
    },
1648
14
    { &hf_ansi_801_loc_uncrtnty_p,
1649
14
      { "Std dev of axis perpendicular to angle specified for pos uncertainty (LOC_UNCRTNTY_P)", "ansi_801.loc_uncrtnty_p",
1650
14
        FT_UINT8, BASE_DEC, NULL, 0x00,
1651
14
        NULL, HFILL }
1652
14
    },
1653
14
    { &hf_ansi_801_fix_type,
1654
14
      { "Fix type (FIX_TYPE)", "ansi_801.fix_type",
1655
14
        FT_BOOLEAN, BASE_NONE, TFS(&ansi_801_fix_type_vals), 0x00,
1656
14
        NULL, HFILL }
1657
14
    },
1658
14
    { &hf_ansi_801_velocity_incl,
1659
14
      { "Velocity information included (VELOCITY_INCL)", "ansi_801.velocity_incl",
1660
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1661
14
        NULL, HFILL }
1662
14
    },
1663
14
    { &hf_ansi_801_velocity_hor,
1664
14
      { "Horizontal velocity magnitude (VELOCITY_HOR)", "ansi_801.velocity_hor",
1665
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1666
14
        NULL, HFILL }
1667
14
    },
1668
14
    { &hf_ansi_801_heading,
1669
14
      { "Heading (HEADING)", "ansi_801.heading",
1670
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1671
14
        NULL, HFILL }
1672
14
    },
1673
14
    { &hf_ansi_801_velocity_ver,
1674
14
      { "Vertical velocity (VELOCITY_VER)", "ansi_801.velocity_ver",
1675
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1676
14
        NULL, HFILL }
1677
14
    },
1678
14
    { &hf_ansi_801_clock_incl,
1679
14
      { "Clock information included (CLOCK_INCL)", "ansi_801.clock_incl",
1680
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1681
14
        NULL, HFILL }
1682
14
    },
1683
14
    { &hf_ansi_801_clock_bias,
1684
14
      { "Clock bias (CLOCK_BIAS)", "ansi_801.clock_bias",
1685
14
        FT_INT24, BASE_DEC, NULL, 0x00,
1686
14
        NULL, HFILL }
1687
14
    },
1688
14
    { &hf_ansi_801_clock_drift,
1689
14
      { "Clock drift (CLOCK_DRIFT)", "ansi_801.clock_drift",
1690
14
        FT_INT16, BASE_DEC, NULL, 0x00,
1691
14
        NULL, HFILL }
1692
14
    },
1693
14
    { &hf_ansi_801_height_incl,
1694
14
      { "Height information included (HEIGHT_INCL)", "ansi_801.height_incl",
1695
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1696
14
        NULL, HFILL }
1697
14
    },
1698
14
    { &hf_ansi_801_height,
1699
14
      { "Height (HEIGHT)", "ansi_801.height",
1700
14
        FT_INT16, BASE_DEC, NULL, 0x00,
1701
14
        NULL, HFILL }
1702
14
    },
1703
14
    { &hf_ansi_801_loc_uncrtnty_v,
1704
14
      { "Std dev of vertical error for pos uncertainty (LOC_UNCRTNTY_V)", "ansi_801.loc_uncrtnty_v",
1705
14
        FT_UINT8, BASE_DEC, NULL, 0x00,
1706
14
        NULL, HFILL }
1707
14
    },
1708
14
    { &hf_ansi_801_reserved_bits,
1709
14
      { "Reserved bit(s)","ansi_801.reserved_bits",
1710
14
        FT_UINT8,BASE_DEC, NULL, 0x0,
1711
14
        NULL, HFILL }
1712
14
    },
1713
14
    { &hf_ansi_801_bad_sv_present,
1714
14
      { "Bad GPS satellites present (BAD_SV_PRESENT)", "ansi_801.bad_sv_present",
1715
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1716
14
        NULL, HFILL }
1717
14
    },
1718
14
    { &hf_ansi_801_num_bad_sv,
1719
14
      { "Number of bad GPS satellites (NUM_BAD_SV)", "ansi_801.num_bad_sv",
1720
14
        FT_UINT8, BASE_DEC, NULL, 0x00,
1721
14
        NULL, HFILL }
1722
14
    },
1723
14
    { &hf_ansi_801_bad_sv_prn_num,
1724
14
      { "Satellite PRN number (SV_PRN_NUM)", "ansi_801.bad_sv_prn_num",
1725
14
        FT_UINT8, BASE_DEC, NULL, 0x00,
1726
14
        NULL, HFILL }
1727
14
    },
1728
14
    { &hf_ansi_801_dopp_req,
1729
14
      { "Doppler (0th order) term requested (DOPP_REQ)", "ansi_801.dopp_req",
1730
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1731
14
        NULL, HFILL }
1732
14
    },
1733
14
    { &hf_ansi_801_add_dopp_req,
1734
14
      { "Additional Doppler terms requested (ADD_DOPP_REQ)", "ansi_801.add_dopp_req",
1735
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1736
14
        NULL, HFILL }
1737
14
    },
1738
14
    { &hf_ansi_801_code_ph_par_req,
1739
14
      { "Code phase parameters requested (CODE_PH_PAR_REQ)", "ansi_801.code_ph_par_req",
1740
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1741
14
        NULL, HFILL }
1742
14
    },
1743
14
    { &hf_ansi_801_az_el_req,
1744
14
      { "Azimuth and elevation angle requested (AZ_EL_REQ)", "ansi_801.az_el_req",
1745
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1746
14
        NULL, HFILL }
1747
14
    },
1748
14
    { &hf_ansi_801_pref_resp_qual,
1749
14
      { "Preferred response quality (PREF_RESP_QUAL)", "ansi_801.pref_resp_qual",
1750
14
        FT_UINT24, BASE_DEC, NULL, 0xe00000,
1751
14
        NULL, HFILL }
1752
14
    },
1753
14
    { &hf_ansi_801_num_fixes,
1754
14
      { "Number of fixes (NUM_FIXES)", "ansi_801.num_fixes",
1755
14
        FT_UINT24, BASE_DEC, NULL, 0x1fe000,
1756
14
        NULL, HFILL }
1757
14
    },
1758
14
    { &hf_ansi_801_t_betw_fixes,
1759
14
      { "Time between fixes (T_BETW_FIXES) (in seconds)", "ansi_801.t_betw_fixes",
1760
14
        FT_UINT24, BASE_DEC, NULL, 0x001fe0,
1761
14
        NULL, HFILL }
1762
14
    },
1763
14
    { &hf_ansi_801_offset_req,
1764
14
      { "Offset requested (OFFSET_REQ)", "ansi_801.offset_req",
1765
14
        FT_BOOLEAN, 24, TFS(&tfs_requested_not_requested), 0x000010,
1766
14
        NULL, HFILL }
1767
14
    },
1768
1769
    /* Generated from convert_proto_tree_add_text.pl */
1770
14
    { &hf_ansi_801_desired_pilot_phase_resolution,
1771
14
      { "Desired pilot phase resolution", "ansi_801.desired_pilot_phase_resolution",
1772
14
        FT_BOOLEAN, 24, TFS(&tfs_desired_pilot_phase_resolution), 0x000008,
1773
14
        NULL, HFILL }
1774
14
    },
1775
14
    { &hf_ansi_801_reserved_24_7,
1776
14
      { "Reserved", "ansi_801.reserved",
1777
14
        FT_UINT24, BASE_HEX, NULL, 0x07,
1778
14
        NULL, HFILL }
1779
14
    },
1780
14
    { &hf_ansi_801_for_req_loc_height_information,
1781
14
      { "Height information", "ansi_801.height_incl",
1782
14
        FT_BOOLEAN, 24, TFS(&tfs_requested_not_requested), 0x000010,
1783
14
        NULL, HFILL }
1784
14
    },
1785
14
    { &hf_ansi_801_for_req_loc_clock_correction_for_gps_time,
1786
14
      { "Clock correction for GPS time", "ansi_801.clock_correction_for_gps_time",
1787
14
        FT_BOOLEAN, 24, TFS(&tfs_requested_not_requested), 0x000008,
1788
14
        NULL, HFILL }
1789
14
    },
1790
14
    { &hf_ansi_801_for_req_loc_velocity_information,
1791
14
      { "Velocity information", "ansi_801.velocity_information",
1792
14
        FT_BOOLEAN, 24, TFS(&tfs_requested_not_requested), 0x000004,
1793
14
        NULL, HFILL }
1794
14
    },
1795
14
    { &hf_ansi_801_reserved24_3,
1796
14
      { "Reserved", "ansi_801.reserved",
1797
14
        FT_UINT24, BASE_HEX, NULL, 0x000003,
1798
14
        NULL, HFILL }
1799
14
    },
1800
14
    { &hf_ansi_801_use_action_time_indicator,
1801
14
      { "Use action time indicator", "ansi_801.use_action_time_indicator",
1802
14
        FT_BOOLEAN, 8, NULL, 0x80,
1803
14
        NULL, HFILL }
1804
14
    },
1805
14
    { &hf_ansi_801_action_time,
1806
14
      { "Action time", "ansi_801.action_time",
1807
14
        FT_UINT8, BASE_DEC, NULL, 0x7E,
1808
14
        NULL, HFILL }
1809
14
    },
1810
14
    { &hf_ansi_801_reserved8_7F,
1811
14
      { "Reserved", "ansi_801.reserved",
1812
14
        FT_UINT8, BASE_HEX, NULL, 0x7F,
1813
14
        NULL, HFILL }
1814
14
    },
1815
14
    { &hf_ansi_801_cancellation_type,
1816
14
      { "Cancellation Type", "ansi_801.cancellation_type",
1817
14
        FT_UINT8, BASE_DEC, VALS(for_req_type_strings), 0xF0,
1818
14
        NULL, HFILL }
1819
14
    },
1820
14
    { &hf_ansi_801_reserved8_0F,
1821
14
      { "Reserved", "ansi_801.reserved",
1822
14
        FT_UINT8, BASE_HEX, NULL, 0x0F,
1823
14
        NULL, HFILL }
1824
14
    },
1825
14
    { &hf_ansi_801_reject_request_type,
1826
14
      { "Reject request type", "ansi_801.reject_request_type",
1827
14
        FT_UINT8, BASE_DEC, VALS(rev_req_type_strings), 0xF0,
1828
14
        NULL, HFILL }
1829
14
    },
1830
14
    { &hf_ansi_801_reject_reason,
1831
14
      { "Reject reason", "ansi_801.reject_reason",
1832
14
        FT_UINT8, BASE_DEC, NULL, 0x0E,
1833
14
        NULL, HFILL }
1834
14
    },
1835
14
    { &hf_ansi_801_reserved8_01,
1836
14
      { "Reserved", "ansi_801.reserved",
1837
14
        FT_UINT8, BASE_HEX, NULL, 0x01,
1838
14
        NULL, HFILL }
1839
14
    },
1840
14
    { &hf_ansi_801_bs_ls_rev,
1841
14
      { "BS_LS_REV", "ansi_801.bs_ls_rev",
1842
14
        FT_UINT8, BASE_HEX, NULL, 0xfc,
1843
14
        NULL, HFILL }
1844
14
    },
1845
14
    { &hf_ansi_801_gps_capability_indicator,
1846
14
      { "GPSC_ID: GPS capability indicator", "ansi_801.gps_capability_indicator",
1847
14
        FT_UINT8, BASE_DEC, NULL, 0x02,
1848
14
        NULL, HFILL }
1849
14
    },
1850
14
    { &hf_ansi_801_afltc_id,
1851
14
      { "AFLTC_ID: Advanced forward link trilateration capability indicator", "ansi_801.afltc_id",
1852
14
        FT_UINT8, BASE_DEC, NULL, 0x01,
1853
14
        NULL, HFILL }
1854
14
    },
1855
14
    { &hf_ansi_801_apdc_id,
1856
14
      { "APDC_ID: Autonomous position determination capability indicator: Autonomous Location Technology Identifier", "ansi_801.apdc_id",
1857
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
1858
14
        NULL, HFILL }
1859
14
    },
1860
14
    { &hf_ansi_801_ref_bit_num,
1861
14
      { "REF_BIT_NUM", "ansi_801.ref_bit_num",
1862
14
        FT_UINT16, BASE_DEC, NULL, 0xffe0,
1863
14
        NULL, HFILL }
1864
14
    },
1865
14
    { &hf_ansi_801_num_dr_p,
1866
14
      { "NUM_DR_P: Number of data records in this part", "ansi_801.num_dr_p",
1867
14
        FT_UINT16, BASE_DEC, NULL, 0x001e,
1868
14
        NULL, HFILL }
1869
14
    },
1870
14
    { &hf_ansi_801_dr_size,
1871
14
      { "DR_SIZE: Data record size", "ansi_801.dr_size",
1872
14
        FT_UINT24, BASE_DEC, NULL, 0x0001FE,
1873
14
        NULL, HFILL }
1874
14
    },
1875
14
    { &hf_ansi_801_part_num,
1876
14
      { "PART_NUM: The part number", "ansi_801.part_num",
1877
14
        FT_UINT16, BASE_DEC, NULL, 0x01c0,
1878
14
        NULL, HFILL }
1879
14
    },
1880
14
    { &hf_ansi_801_total_parts,
1881
14
      { "TOTAL_PARTS: Total number of parts", "ansi_801.total_parts",
1882
14
        FT_UINT16, BASE_DEC, NULL, 0x38,
1883
14
        NULL, HFILL }
1884
14
    },
1885
14
    { &hf_ansi_801_data_records,
1886
14
      { "Data records", "ansi_801.data_records",
1887
14
        FT_UINT16, BASE_DEC, NULL, 0x07,
1888
14
        NULL, HFILL }
1889
14
    },
1890
14
    { &hf_ansi_801_num_sv_p32,
1891
14
      { "NUM_SV_P: Number of satellites in this part", "ansi_801.num_sv_p",
1892
14
        FT_UINT32, BASE_DEC, NULL, 0xfc000000,
1893
14
        NULL, HFILL }
1894
14
    },
1895
14
    { &hf_ansi_801_week_num,
1896
14
      { "WEEK_NUM: The GPS week number of the almanac", "ansi_801.week_num",
1897
14
        FT_UINT32, BASE_DEC, NULL, 0x03fc0000,
1898
14
        NULL, HFILL }
1899
14
    },
1900
14
    { &hf_ansi_801_toa,
1901
14
      { "TOA: The reference time of the almanac", "ansi_801.toa",
1902
14
        FT_UINT32, BASE_DEC, NULL, 0x0003fc00,
1903
14
        NULL, HFILL }
1904
14
    },
1905
14
    { &hf_ansi_801_part_num32,
1906
14
      { "PART_NUM: The part number", "ansi_801.part_num",
1907
14
        FT_UINT32, BASE_DEC, NULL, 0x000003e0,
1908
14
        NULL, HFILL }
1909
14
    },
1910
14
    { &hf_ansi_801_total_parts32,
1911
14
      { "TOTAL_PARTS: The total number of parts", "ansi_801.total_parts",
1912
14
        FT_UINT32, BASE_DEC, NULL, 0x0000001f,
1913
14
        NULL, HFILL }
1914
14
    },
1915
14
    { &hf_ansi_801_num_sv_p16,
1916
14
      { "NUM_SV_P: Number of satellites in this part", "ansi_801.num_sv_p",
1917
14
        FT_UINT16, BASE_DEC, NULL, 0xfc00,
1918
14
        NULL, HFILL }
1919
14
    },
1920
14
    { &hf_ansi_801_part_num16,
1921
14
      { "PART_NUM: The part number", "ansi_801.part_num",
1922
14
        FT_UINT16, BASE_DEC, NULL, 0x03e0,
1923
14
        NULL, HFILL }
1924
14
    },
1925
14
    { &hf_ansi_801_total_parts16,
1926
14
      { "TOTAL_PARTS: The total number of parts", "ansi_801.total_parts",
1927
14
        FT_UINT16, BASE_DEC, NULL, 0x001f,
1928
14
        NULL, HFILL }
1929
14
    },
1930
14
    { &hf_ansi_801_coordinate_type_requested,
1931
14
      { "Coordinate type requested", "ansi_801.coordinate_type_requested",
1932
14
        FT_BOOLEAN, 8, TFS(&tfs_spherical_cartesian), 0x80,
1933
14
        NULL, HFILL }
1934
14
    },
1935
14
    { &hf_ansi_801_extended_base_station_almanac,
1936
14
      { "Extended base station almanac", "ansi_801.extended_base_station_almanac",
1937
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x80,
1938
14
        NULL, HFILL }
1939
14
    },
1940
14
    { &hf_ansi_801_alpha_and_beta_parameters,
1941
14
      { "Alpha and Beta parameters", "ansi_801.alpha_and_beta_parameters",
1942
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x80,
1943
14
        NULL, HFILL }
1944
14
    },
1945
14
    { &hf_ansi_801_subframes_4_and_5,
1946
14
      { "Subframes 4 and 5", "ansi_801.subframes_4_and_5",
1947
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x80,
1948
14
        NULL, HFILL }
1949
14
    },
1950
14
    { &hf_ansi_801_rev_req_loc_height_information,
1951
14
      { "Height information", "ansi_801.height_information",
1952
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x80,
1953
14
        NULL, HFILL }
1954
14
    },
1955
14
    { &hf_ansi_801_rev_req_loc_clock_correction_for_gps_time,
1956
14
      { "Clock correction for GPS time", "ansi_801.clock_correction_for_gps_time",
1957
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x40,
1958
14
        NULL, HFILL }
1959
14
    },
1960
14
    { &hf_ansi_801_rev_req_loc_velocity_information,
1961
14
      { "Velocity information", "ansi_801.velocity_information",
1962
14
        FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x20,
1963
14
        NULL, HFILL }
1964
14
    },
1965
14
    { &hf_ansi_801_reserved8_1F,
1966
14
      { "Reserved", "ansi_801.reserved",
1967
14
        FT_UINT8, BASE_HEX, NULL, 0x1F,
1968
14
        NULL, HFILL }
1969
14
    },
1970
14
    { &hf_ansi_801_ms_ls_rev,
1971
14
      { "MS_LS_REV", "ansi_801.ms_ls_rev",
1972
14
        FT_UINT16, BASE_DEC, NULL, 0xfc00,
1973
14
        NULL, HFILL }
1974
14
    },
1975
14
    { &hf_ansi_801_ms_mode,
1976
14
      { "MS_MODE", "ansi_801.ms_mode",
1977
14
        FT_UINT16, BASE_DEC, NULL, 0x03c0,
1978
14
        NULL, HFILL }
1979
14
    },
1980
14
    { &hf_ansi_801_pilot_ph_cap,
1981
14
      { "PILOT_PH_CAP", "ansi_801.pilot_ph_cap",
1982
14
        FT_UINT16, BASE_DEC, NULL, 0x003f,
1983
14
        NULL, HFILL }
1984
14
    },
1985
14
    { &hf_ansi_801_gps_acq_cap,
1986
14
      { "GPS_ACQ_CAP", "ansi_801.gps_acq_cap",
1987
14
        FT_UINT24, BASE_HEX, NULL, 0x000FFF,
1988
14
        NULL, HFILL }
1989
14
    },
1990
14
    { &hf_ansi_801_reserved_24_F80000,
1991
14
      { "Reserved", "ansi_801.reserved",
1992
14
        FT_UINT24, BASE_HEX, NULL, 0xf80000,
1993
14
        NULL, HFILL }
1994
14
    },
1995
14
    { &hf_ansi_801_gps_autonomous_acquisition_capable,
1996
14
      { "GPS Autonomous Acquisition Capable", "ansi_801.gps_autonomous_acquisition_capable",
1997
14
        FT_BOOLEAN, 24, NULL, 0x040000,
1998
14
        NULL, HFILL }
1999
14
    },
2000
14
    { &hf_ansi_801_gps_almanac_correction,
2001
14
      { "GPS Almanac Correction", "ansi_801.gps_almanac_correction",
2002
14
        FT_BOOLEAN, 24, NULL, 0x020000,
2003
14
        NULL, HFILL }
2004
14
    },
2005
14
    { &hf_ansi_801_gps_navigation_message_bits,
2006
14
      { "GPS Navigation Message Bits", "ansi_801.gps_navigation_message_bits",
2007
14
        FT_BOOLEAN, 24, NULL, 0x010000,
2008
14
        NULL, HFILL }
2009
14
    },
2010
14
    { &hf_ansi_801_gps_ephemeris,
2011
14
      { "GPS Ephemeris", "ansi_801.gps_ephemeris",
2012
14
        FT_BOOLEAN, 24, NULL, 0x008000,
2013
14
        NULL, HFILL }
2014
14
    },
2015
14
    { &hf_ansi_801_gps_almanac,
2016
14
      { "GPS Almanac", "ansi_801.gps_almanac",
2017
14
        FT_BOOLEAN, 24, NULL, 0x004000,
2018
14
        NULL, HFILL }
2019
14
    },
2020
14
    { &hf_ansi_801_gps_sensitivity_assistance,
2021
14
      { "GPS Sensitivity Assistance", "ansi_801.gps_sensitivity_assistance",
2022
14
        FT_BOOLEAN, 24, NULL, 0x002000,
2023
14
        NULL, HFILL }
2024
14
    },
2025
14
    { &hf_ansi_801_gps_acquisition_assistance,
2026
14
      { "GPS Acquisition Assistance", "ansi_801.gps_acquisition_assistance",
2027
14
        FT_BOOLEAN, 24, NULL, 0x001000,
2028
14
        NULL, HFILL }
2029
14
    },
2030
14
    { &hf_ansi_801_loc_calc_cap,
2031
14
      { "LOC_CALC_CAP", "ansi_801.loc_calc_cap",
2032
14
        FT_UINT24, BASE_HEX, NULL, 0x000FFF,
2033
14
        NULL, HFILL }
2034
14
    },
2035
14
    { &hf_ansi_801_pre_programmed_location,
2036
14
      { "Pre-programmed Location", "ansi_801.pre_programmed_location",
2037
14
        FT_BOOLEAN, 24, NULL, 0x000800,
2038
14
        NULL, HFILL }
2039
14
    },
2040
14
    { &hf_ansi_801_reserved_24_700,
2041
14
      { "Reserved", "ansi_801.reserved",
2042
14
        FT_UINT24, BASE_HEX, NULL, 0x000700,
2043
14
        NULL, HFILL }
2044
14
    },
2045
14
    { &hf_ansi_801_hybrid_gps_and_aflt_lcc,
2046
14
      { "Hybrid GPS and AFLT Location Calculation Capable", "ansi_801.hybrid_gps_and_aflt_lcc",
2047
14
        FT_BOOLEAN, 24, NULL, 0x000080,
2048
14
        NULL, HFILL }
2049
14
    },
2050
14
    { &hf_ansi_801_autonomous_location_calculation_capable,
2051
14
      { "Autonomous Location Calculation Capable", "ansi_801.autonomous_lcc",
2052
14
        FT_BOOLEAN, 24, NULL, 0x000040,
2053
14
        NULL, HFILL }
2054
14
    },
2055
14
    { &hf_ansi_801_lcc_using_gps_almanac_correction,
2056
14
      { "Location Calculation Capable using GPS Almanac Correction", "ansi_801.lcc_using_gps_almanac_correction",
2057
14
        FT_BOOLEAN, 24, NULL, 0x000020,
2058
14
        NULL, HFILL }
2059
14
    },
2060
14
    { &hf_ansi_801_lcc_using_gps_ephemeris_assistance,
2061
14
      { "Location Calculation Capable using GPS Ephemeris Assistance", "ansi_801.lcc_using_gps_ephemeris_assistance",
2062
14
        FT_BOOLEAN, 24, NULL, 0x000010,
2063
14
        NULL, HFILL }
2064
14
    },
2065
14
    { &hf_ansi_801_lcc_using_gps_almanac_assistance,
2066
14
      { "Location Calculation Capable using GPS Almanac Assistance", "ansi_801.lcc_using_gps_almanac_assistance",
2067
14
        FT_BOOLEAN, 24, NULL, 0x000008,
2068
14
        NULL, HFILL }
2069
14
    },
2070
14
    { &hf_ansi_801_aflt_lcc,
2071
14
      { "Advanced Forward Link Trilateration (AFLT) Location Calculation Capable", "ansi_801.aflt_lcc",
2072
14
        FT_BOOLEAN, 24, NULL, 0x000004,
2073
14
        NULL, HFILL }
2074
14
    },
2075
14
    { &hf_ansi_801_lcc_using_location_assistance_cartesian,
2076
14
      { "Location Calculation Capable using Location Assistance - Cartesian", "ansi_801.lcc_using_location_assistance.cartesian",
2077
14
        FT_BOOLEAN, 24, NULL, 0x000002,
2078
14
        NULL, HFILL }
2079
14
    },
2080
14
    { &hf_ansi_801_lcc_capable_using_location_assistance_spherical,
2081
14
      { "Location Calculation Capable using Location Assistance - Spherical", "ansi_801.lcc_using_location_assistance.spherical",
2082
14
        FT_BOOLEAN, 24, NULL, 0x000001,
2083
14
        NULL, HFILL }
2084
14
    },
2085
14
    { &hf_ansi_801_ref_pn,
2086
14
      { "REF_PN", "ansi_801.ref_pn",
2087
14
        FT_UINT24, BASE_DEC, NULL, 0xff8000,
2088
14
        NULL, HFILL }
2089
14
    },
2090
14
    { &hf_ansi_801_mob_sys_t_offset,
2091
14
      { "MOB_SYS_T_OFFSET", "ansi_801.mob_sys_t_offset",
2092
14
        FT_UINT24, BASE_DEC, NULL, 0x007ffe,
2093
14
        NULL, HFILL }
2094
14
    },
2095
14
    { &hf_ansi_801_reserved24_1,
2096
14
      { "Reserved", "ansi_801.reserved",
2097
14
        FT_UINT24, BASE_HEX, NULL, 0x000001,
2098
14
        NULL, HFILL }
2099
14
    },
2100
14
    { &hf_ansi_801_no_outstanding_request_element,
2101
14
      { "No outstanding request element", "ansi_801.no_outstanding_request_element",
2102
14
        FT_BOOLEAN, 8, NULL, 0x08,
2103
14
        NULL, HFILL }
2104
14
    },
2105
14
    { &hf_ansi_801_reserved8_07,
2106
14
      { "Reserved", "ansi_801.reserved",
2107
14
        FT_UINT8, BASE_HEX, NULL, 0x07,
2108
14
        NULL, HFILL }
2109
14
    },
2110
14
    { &hf_ansi_801_reserved8_F0,
2111
14
      { "Reserved", "ansi_801.reserved",
2112
14
        FT_UINT8, BASE_HEX, NULL, 0xF0,
2113
14
        NULL, HFILL }
2114
14
    },
2115
14
    { &hf_ansi_801_for_request_length,
2116
14
      { "Length", "ansi_801.for_request_length",
2117
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
2118
14
        NULL, HFILL }
2119
14
    },
2120
14
    { &hf_ansi_801_reserved8_E0,
2121
14
      { "Reserved", "ansi_801.reserved",
2122
14
        FT_UINT8, BASE_HEX, NULL, 0xE0,
2123
14
        NULL, HFILL }
2124
14
    },
2125
14
    { &hf_ansi_801_unsolicited_response_indicator,
2126
14
      { "Unsolicited response indicator", "ansi_801.unsolicited_response_indicator",
2127
14
        FT_BOOLEAN, 8, NULL, 0x10,
2128
14
        NULL, HFILL }
2129
14
    },
2130
14
    { &hf_ansi_801_for_response_length,
2131
14
      { "Length", "ansi_801.for_response_length",
2132
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
2133
14
        NULL, HFILL }
2134
14
    },
2135
14
    { &hf_ansi_801_rev_request_length,
2136
14
      { "Length", "ansi_801.rev_request_length",
2137
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
2138
14
        NULL, HFILL }
2139
14
    },
2140
14
    { &hf_ansi_801_rev_response_length,
2141
14
      { "Length", "ansi_801.rev_response_length",
2142
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
2143
14
        NULL, HFILL }
2144
14
    },
2145
14
    { &hf_ansi_801_session_start,
2146
14
      { "Session Start", "ansi_801.session_start",
2147
14
        FT_BOOLEAN, 8, NULL, 0x80,
2148
14
        NULL, HFILL }
2149
14
    },
2150
14
    { &hf_ansi_801_session_end,
2151
14
      { "Session End", "ansi_801.session_end",
2152
14
        FT_BOOLEAN, 8, NULL, 0x40,
2153
14
        NULL, HFILL }
2154
14
    },
2155
14
    { &hf_ansi_801_session_source,
2156
14
      { "Session Source", "ansi_801.session_source",
2157
14
        FT_BOOLEAN, 8, NULL, 0x20,
2158
14
        NULL, HFILL }
2159
14
    },
2160
14
    { &hf_ansi_801_pd_message_type,
2161
14
      { "PD Message Type", "ansi_801.pd_message_type",
2162
14
        FT_UINT8, BASE_DEC, NULL, 0x0,
2163
14
        NULL, HFILL }
2164
14
    },
2165
14
    { &hf_ansi_801_pd_message_len,
2166
14
      { "PD Message Length", "ansi_801.pd_message_len",
2167
14
        FT_UINT16, BASE_DEC, NULL, 0xffc0,
2168
14
        NULL, HFILL }
2169
14
    },
2170
14
    { &hf_ansi_801_regulatory_services_indicator,
2171
14
      { "Regulatory Services Indicator", "ansi_801.regulatory_services_indicator",
2172
14
        FT_UINT16, BASE_DEC, VALS(regulatory_services_indicator_vals), 0x0030,
2173
14
        NULL, HFILL }
2174
14
    },
2175
14
    { &hf_ansi_801_for_message_number_requests16,
2176
14
      { "Number Requests", "ansi_801.for_message_number_requests",
2177
14
        FT_UINT16, BASE_DEC, NULL, 0x0F,
2178
14
        NULL, HFILL }
2179
14
    },
2180
14
    { &hf_ansi_801_for_message_number_responsesF0,
2181
14
      { "Number Responses", "ansi_801.for_message_number_responses",
2182
14
        FT_UINT8, BASE_DEC, NULL, 0xF0,
2183
14
        NULL, HFILL }
2184
14
    },
2185
14
    { &hf_ansi_801_for_message_number_requests8,
2186
14
      { "Number Requests", "ansi_801.for_message_number_requests",
2187
14
        FT_UINT8, BASE_DEC, NULL, 0xF0,
2188
14
        NULL, HFILL }
2189
14
    },
2190
14
    { &hf_ansi_801_for_message_number_responses0F,
2191
14
      { "Number Responses", "ansi_801.for_message_number_responses",
2192
14
        FT_UINT8, BASE_DEC, NULL, 0x0F,
2193
14
        NULL, HFILL }
2194
14
    },
2195
14
    { &hf_ansi_801_rev_message_number_requests16,
2196
14
      { "Number Requests", "ansi_801.rev_message_number_requests",
2197
14
        FT_UINT16, BASE_DEC, NULL, 0x0F,
2198
14
        NULL, HFILL }
2199
14
    },
2200
14
    { &hf_ansi_801_rev_message_number_responsesF0,
2201
14
      { "Number Responses", "ansi_801.rev_message_number_responses",
2202
14
        FT_UINT8, BASE_DEC, NULL, 0xF0,
2203
14
        NULL, HFILL }
2204
14
    },
2205
14
    { &hf_ansi_801_rev_message_number_requests8,
2206
14
      { "Number Requests", "ansi_801.rev_message_number_requests",
2207
14
        FT_UINT8, BASE_DEC, NULL, 0xF0,
2208
14
        NULL, HFILL }
2209
14
    },
2210
14
    { &hf_ansi_801_rev_message_number_responses0F,
2211
14
      { "Number Responses", "ansi_801.rev_message_number_responses",
2212
14
        FT_UINT8, BASE_DEC, NULL, 0x0F,
2213
14
        NULL, HFILL }
2214
14
    },
2215
14
    { &hf_ansi_801_data,
2216
14
      { "Data", "ansi_801.data",
2217
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
2218
14
        NULL, HFILL }
2219
14
    },
2220
14
    { &hf_ansi_801_proprietary_data,
2221
14
      { "Reserved/Proprietary/Future Data", "ansi_801.proprietary_data",
2222
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
2223
14
        NULL, HFILL }
2224
14
    },
2225
14
    { &hf_ansi_801_time_ref_ms,
2226
14
      { "TIME_REF_MS", "ansi_801.time_ref_ms",
2227
14
        FT_UINT24, BASE_DEC, NULL, 0x0,
2228
14
        NULL, HFILL }
2229
14
    },
2230
14
    { &hf_ansi_801_time_of_almanac,
2231
14
      { "Time of almanac", "ansi_801.time_of_almanac",
2232
14
        FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_time_of_almanac), 0x0,
2233
14
        NULL, HFILL }
2234
14
    },
2235
14
    { &hf_ansi_801_gps_week_number,
2236
14
      { "GPS week number", "ansi_801.gps_week_number",
2237
14
        FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_gps_week_number), 0x0,
2238
14
        NULL, HFILL }
2239
14
    },
2240
14
  };
2241
2242
  /* Setup protocol subtree array */
2243
14
#define NUM_INDIVIDUAL_PARAMS 3
2244
14
  int *ett[NUM_INDIVIDUAL_PARAMS+NUM_FOR_REQ_TYPE+NUM_FOR_RSP_TYPE+NUM_REV_REQ_TYPE+NUM_REV_RSP_TYPE];
2245
2246
2247
14
  static ei_register_info ei[] = {
2248
14
    { &ei_ansi_801_extraneous_data, { "ansi_801.extraneous_data", PI_PROTOCOL, PI_NOTE, "Extraneous Data, dissector bug or later version spec (report to wireshark.org)", EXPFILL }},
2249
14
    { &ei_ansi_801_short_data, { "ansi_801.short_data", PI_PROTOCOL, PI_NOTE, "Short Data (?) - try checking decoder variant preference or dissector bug/later version spec (report to wireshark.org)", EXPFILL }},
2250
14
    { &ei_ansi_801_unexpected_length, { "ansi_801.unexpected_length", PI_PROTOCOL, PI_WARN, "Unexpected Data Length - try checking decoder variant preference or dissector bug/later version spec (report to wireshark.org)", EXPFILL }},
2251
14
  };
2252
2253
14
  expert_module_t* expert_ansi_801;
2254
2255
14
  ett[0] = &ett_ansi_801;
2256
14
  ett[1] = &ett_gps;
2257
14
  ett[2] = &ett_loc;
2258
2259
14
  last_offset = NUM_INDIVIDUAL_PARAMS;
2260
2261
140
  for (i=0; i < NUM_FOR_REQ_TYPE; i++, last_offset++)
2262
126
  {
2263
126
    ett[last_offset] = &ett_for_req_type[i];
2264
126
  }
2265
2266
210
  for (i=0; i < NUM_FOR_RSP_TYPE; i++, last_offset++)
2267
196
  {
2268
196
    ett[last_offset] = &ett_for_rsp_type[i];
2269
196
  }
2270
2271
210
  for (i=0; i < NUM_REV_REQ_TYPE; i++, last_offset++)
2272
196
  {
2273
196
    ett[last_offset] = &ett_rev_req_type[i];
2274
196
  }
2275
2276
140
  for (i=0; i < NUM_REV_RSP_TYPE; i++, last_offset++)
2277
126
  {
2278
126
    ett[last_offset] = &ett_rev_rsp_type[i];
2279
126
  }
2280
2281
  /* Register the protocol name and description */
2282
14
  proto_ansi_801 =
2283
14
    proto_register_protocol("ANSI IS-801 (Location Services (PLD))", "ANSI IS-801 (Location Services (PLD))", "ansi_801");
2284
2285
  /* Required function calls to register the header fields and subtrees used */
2286
14
  proto_register_field_array(proto_ansi_801, hf, array_length(hf));
2287
14
  proto_register_subtree_array(ett, array_length(ett));
2288
14
  expert_ansi_801 = expert_register_protocol(proto_ansi_801);
2289
14
  expert_register_field_array(expert_ansi_801, ei, array_length(ei));
2290
2291
  /* subdissector code */
2292
14
  ansi_801_handle = register_dissector("ansi_801", dissect_ansi_801, proto_ansi_801);
2293
14
}
2294
2295
2296
void
2297
proto_reg_handoff_ansi_801(void)
2298
14
{
2299
14
  dissector_add_uint("ansi_map.pld", ANSI_801_FORWARD, ansi_801_handle);
2300
14
  dissector_add_uint("ansi_map.pld", ANSI_801_REVERSE, ansi_801_handle);
2301
14
  dissector_add_uint("ansi_a.pld",   ANSI_801_FORWARD, ansi_801_handle);
2302
14
  dissector_add_uint("ansi_a.pld",   ANSI_801_REVERSE, ansi_801_handle);
2303
14
}
2304
2305
/*
2306
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2307
 *
2308
 * Local variables:
2309
 * c-basic-offset: 8
2310
 * tab-width: 8
2311
 * indent-tabs-mode: t
2312
 * End:
2313
 *
2314
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2315
 * :indentSize=8:tabSize=8:noTabs=false:
2316
 */