1 /* packet-ppi-vector.c
2 * Routines for PPI-GEOLOCATION-VECTOR dissection
3 * Copyright 2010, Harris Corp, jellch@harris.com
4 *
5 * See
6 *
7 * http://new.11mercenary.net/~johnycsh/ppi_geolocation_spec/
8 *
9 * for specifications.
10 *
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
14 *
15 * Copied from packet-radiotap.c
16 *
17 * SPDX-License-Identifier: GPL-2.0-or-later
18 */
19
20 #include "config.h"
21
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include "packet-ppi-geolocation-common.h"
25
26 enum ppi_vector_type {
27 PPI_VECTOR_VFLAGS = 0,
28 PPI_VECTOR_VCHARS = 1,
29 PPI_VECTOR_ROTX = 2,
30 PPI_VECTOR_ROTY = 3,
31 PPI_VECTOR_ROTZ = 4,
32
33 /* V1 */
34 PPI_VECTOR_OFF_R = 5,
35 PPI_VECTOR_OFF_F = 6,
36 PPI_VECTOR_OFF_U = 7,
37 PPI_VECTOR_VEL_R = 8,
38 PPI_VECTOR_VEL_F = 9,
39 PPI_VECTOR_VEL_U = 10,
40 PPI_VECTOR_VEL_T = 11,
41 PPI_VECTOR_ACC_R = 12,
42 PPI_VECTOR_ACC_F = 13,
43 PPI_VECTOR_ACC_U = 14,
44 PPI_VECTOR_ACC_T = 15,
45
46 /* V2 */
47 PPI_VECTOR_OFF_X = 5,
48 PPI_VECTOR_OFF_Y = 6,
49 PPI_VECTOR_OFF_Z = 7,
50
51 PPI_VECTOR_ERR_ROT = 16,
52 PPI_VECTOR_ERR_OFF = 17,
53
54 /* V1 only */
55 PPI_VECTOR_ERR_VEL = 18,
56 PPI_VECTOR_ERR_ACC = 19,
57
58 PPI_VECTOR_DESCSTR = 28,
59 PPI_VECTOR_APPID = 29,
60 PPI_VECTOR_APPDATA = 30,
61 PPI_VECTOR_EXT = 31
62 };
63 #define PPI_VECTOR_MAXTAGLEN 144 /* increase as fields are added */
64
65 /* There are currently eight vector characteristics.
66 * These are purely descriptive (no mathematical importance)
67 */
68 #define PPI_VECTOR_VCHARS_ANTENNA 0x00000001
69 #define PPI_VECTOR_VCHARS_DIR_OF_TRAVEL 0x00000002
70 #define PPI_VECTOR_VCHARS_FRONT_OF_VEH 0x00000004
71 #define PPI_VECTOR_VCHARS_AOA 0x00000008
72 #define PPI_VECTOR_VCHARS_TRANSMITTER_POS 0x00000010
73
74 #define PPI_VECTOR_VCHARS_GPS_DERIVED 0x00000100
75 #define PPI_VECTOR_VCHARS_INS_DERIVED 0x00000200
76 #define PPI_VECTOR_VCHARS_COMPASS_DERIVED 0x00000400
77 #define PPI_VECTOR_VCHARS_ACCELEROMETER_DERIVED 0x00000800
78 #define PPI_VECTOR_VCHARS_HUMAN_DERIVED 0x00001000
79
80 #define PPI_VECTOR_MASK_VFLAGS 0x00000001
81 #define PPI_VECTOR_MASK_VCHARS 0x00000002
82 #define PPI_VECTOR_MASK_ROTX 0x00000004
83 #define PPI_VECTOR_MASK_ROTY 0x00000008
84 #define PPI_VECTOR_MASK_ROTZ 0x00000010
85
86 /* V1 */
87 #define PPI_VECTOR_MASK_OFF_R 0x00000020
88 #define PPI_VECTOR_MASK_OFF_F 0x00000040
89 #define PPI_VECTOR_MASK_OFF_U 0x00000080
90 #define PPI_VECTOR_MASK_VEL_R 0x00000100
91 #define PPI_VECTOR_MASK_VEL_F 0x00000200
92 #define PPI_VECTOR_MASK_VEL_U 0x00000400
93 #define PPI_VECTOR_MASK_VEL_T 0x00000800
94 #define PPI_VECTOR_MASK_ACC_R 0x00001000
95 #define PPI_VECTOR_MASK_ACC_F 0x00002000
96 #define PPI_VECTOR_MASK_ACC_U 0x00004000
97 #define PPI_VECTOR_MASK_ACC_T 0x00008000
98
99 /* V2 */
100 #define PPI_VECTOR_MASK_OFF_X 0x00000020
101 #define PPI_VECTOR_MASK_OFF_Y 0x00000040
102 #define PPI_VECTOR_MASK_OFF_Z 0x00000080
103
104 #define PPI_VECTOR_MASK_ERR_ROT 0x00010000
105 #define PPI_VECTOR_MASK_ERR_OFF 0x00020000
106
107 /* V1 only */
108 #define PPI_VECTOR_MASK_ERR_VEL 0x00040000
109 #define PPI_VECTOR_MASK_ERR_ACC 0x00080000
110
111 #define PPI_VECTOR_MASK_DESCSTR 0x10000000 /* 28 */
112 #define PPI_VECTOR_MASK_APPID 0x20000000 /* 29 */
113 #define PPI_VECTOR_MASK_APPDATA 0x40000000 /* 30 */
114 #define PPI_VECTOR_MASK_EXT 0x80000000 /* 31 */
115
116 /* There are currently only three vector flags.
117 * These control the units/interpretation of a vector
118 */
119 #define PPI_VECTOR_VFLAGS_DEFINES_FORWARD 0x00000001
120
121 /* V1 */
122 #define PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE 0x00000002
123 #define PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS 0x00000004
124
125 /* V2 */
126 #define PPI_VECTOR_VFLAGS_RELATIVE_TO 0x00000006 /* 2 bits */
127
128 /* Values for the two-bit RelativeTo subfield of vflags */
129 static const value_string relativeto_string[] = {
130 { 0x00, "Forward"},
131 { 0x01, "Earth"},
132 { 0x02, "Current"},
133 { 0x03, "Reserved"},
134 { 0x00, NULL}
135 };
136
137 void proto_register_ppi_vector(void);
138
139 /* protocol */
140 static int proto_ppi_vector = -1;
141
142 /* "top" level fields */
143 static int hf_ppi_vector_version = -1;
144 static int hf_ppi_vector_pad = -1;
145 static int hf_ppi_vector_length = -1;
146 static int hf_ppi_vector_present = -1;
147 static int hf_ppi_vector_vflags = -1;
148 static int hf_ppi_vector_vchars = -1;
149 static int hf_ppi_vector_rot_x = -1;
150 static int hf_ppi_vector_rot_y = -1;
151 static int hf_ppi_vector_rot_z = -1;
152
153 /* V1 */
154 static int hf_ppi_vector_off_r = -1;
155 static int hf_ppi_vector_off_f = -1;
156 static int hf_ppi_vector_off_u = -1;
157 static int hf_ppi_vector_vel_r = -1;
158 static int hf_ppi_vector_vel_f = -1;
159 static int hf_ppi_vector_vel_u = -1;
160 static int hf_ppi_vector_vel_t = -1;
161 static int hf_ppi_vector_acc_r = -1;
162 static int hf_ppi_vector_acc_f = -1;
163 static int hf_ppi_vector_acc_u = -1;
164 static int hf_ppi_vector_acc_t = -1;
165
166 /* V2 */
167 static int hf_ppi_vector_off_x = -1;
168 static int hf_ppi_vector_off_y = -1;
169 static int hf_ppi_vector_off_z = -1;
170
171 static int hf_ppi_vector_err_rot= -1;
172 static int hf_ppi_vector_err_off= -1;
173
174 /* V1 only */
175 static int hf_ppi_vector_err_vel= -1;
176 static int hf_ppi_vector_err_acc= -1;
177
178 static int hf_ppi_vector_descstr= -1;
179 static int hf_ppi_vector_appspecific_num = -1;
180 static int hf_ppi_vector_appspecific_data = -1;
181
182 /* "Present" flags */
183 static int hf_ppi_vector_present_vflags = -1;
184 static int hf_ppi_vector_present_vchars = -1;
185 static int hf_ppi_vector_present_val_x = -1;
186 static int hf_ppi_vector_present_val_y = -1;
187 static int hf_ppi_vector_present_val_z = -1;
188
189 /* V1 */
190 static int hf_ppi_vector_present_off_r = -1;
191 static int hf_ppi_vector_present_off_f = -1;
192 static int hf_ppi_vector_present_off_u = -1;
193 static int hf_ppi_vector_present_vel_r = -1;
194 static int hf_ppi_vector_present_vel_f = -1;
195 static int hf_ppi_vector_present_vel_u = -1;
196 static int hf_ppi_vector_present_vel_t = -1;
197 static int hf_ppi_vector_present_acc_r = -1;
198 static int hf_ppi_vector_present_acc_f = -1;
199 static int hf_ppi_vector_present_acc_u = -1;
200 static int hf_ppi_vector_present_acc_t = -1;
201
202 /* V2 */
203 static int hf_ppi_vector_present_off_x = -1;
204 static int hf_ppi_vector_present_off_y = -1;
205 static int hf_ppi_vector_present_off_z = -1;
206
207 static int hf_ppi_vector_present_err_rot = -1;
208 static int hf_ppi_vector_present_err_off = -1;
209
210 /* V1 only */
211 static int hf_ppi_vector_present_err_vel = -1;
212 static int hf_ppi_vector_present_err_acc = -1;
213
214 static int hf_ppi_vector_present_descstr= -1;
215 static int hf_ppi_vector_presenappsecific_num = -1;
216 static int hf_ppi_vector_present_appspecific_data = -1;
217 static int hf_ppi_vector_present_ext = -1;
218
219 /* VectorFlags bits */
220 /* There are currently only three bits and two fields defined in vector flags.
221 * These control the units/interpretation of a vector
222 */
223 static int hf_ppi_vector_vflags_defines_forward = -1; /* bit 0 */
224
225 /* V1 */
226 static int hf_ppi_vector_vflags_rots_absolute = -1; /* different ways to display the same bit, hi or low */
227 static int hf_ppi_vector_vflags_offsets_from_gps = -1; /* these are different ways to display the same bit, hi or low */
228
229 /* V2 */
230 static int hf_ppi_vector_vflags_relative_to= -1; /* bits 1 and 2 */
231
232 /* There are currently eight vector characteristics.
233 * These are purely descriptive (no mathematical importance)
234 */
235 static int hf_ppi_vector_vchars_antenna = -1;
236 static int hf_ppi_vector_vchars_dir_of_travel = -1;
237 static int hf_ppi_vector_vchars_front_of_veh = -1;
238
239 /* V2 only */
240 static int hf_ppi_vector_vchars_angle_of_arrival= -1;
241 static int hf_ppi_vector_vchars_transmitter_pos= -1;
242
243 static int hf_ppi_vector_vchars_gps_derived = -1;
244 static int hf_ppi_vector_vchars_ins_derived = -1;
245 static int hf_ppi_vector_vchars_compass_derived = -1;
246 static int hf_ppi_vector_vchars_accelerometer_derived = -1;
247 static int hf_ppi_vector_vchars_human_derived = -1;
248 static int hf_ppi_vector_unknown_data = -1;
249
250 /*These represent arrow-dropdownthings in the gui */
251 static gint ett_ppi_vector = -1;
252 static gint ett_ppi_vector_present = -1;
253 static gint ett_ppi_vectorflags= -1;
254 static gint ett_ppi_vectorchars= -1;
255
256 static expert_field ei_ppi_vector_present_bit = EI_INIT;
257 static expert_field ei_ppi_vector_length = EI_INIT;
258
259
260 /* We want to abbreviate this field into a single line. Does so without any string manipulation */
261 static void
annotate_vector_chars(guint32 chars,proto_tree * my_pt)262 annotate_vector_chars(guint32 chars, proto_tree *my_pt)
263 {
264 if (chars & PPI_VECTOR_VCHARS_ANTENNA)
265 proto_item_append_text(my_pt, " (Antenna)");
266 if (chars & PPI_VECTOR_VCHARS_DIR_OF_TRAVEL)
267 proto_item_append_text(my_pt, " (DOT)");
268 if (chars & PPI_VECTOR_VCHARS_FRONT_OF_VEH)
269 proto_item_append_text(my_pt, " (Front_of_veh)");
270 if (chars & PPI_VECTOR_VCHARS_AOA)
271 proto_item_append_text(my_pt, " (AOA)");
272 if (chars & PPI_VECTOR_VCHARS_TRANSMITTER_POS)
273 proto_item_append_text(my_pt, " (TRANSMITTER_POS)");
274 }
275
276 static void
dissect_ppi_vector_v1(tvbuff_t * tvb,packet_info * pinfo,int offset,gint length_remaining,proto_tree * ppi_vector_tree)277 dissect_ppi_vector_v1(tvbuff_t *tvb, packet_info *pinfo, int offset, gint length_remaining, proto_tree *ppi_vector_tree)
278 {
279 proto_tree *vectorflags_tree = NULL;
280 proto_tree *vectorchars_tree = NULL;
281 proto_tree *my_pt, *pt;
282 proto_item *ti;
283
284 /* bits */
285 int bit;
286 guint32 present, next_present;
287 /* values actually read out, for displaying */
288 gdouble rot_x, rot_y, rot_z;
289 gdouble off_r, off_f, off_u;
290 gdouble vel_r, vel_f, vel_u, vel_t;
291 gdouble acc_r, acc_f, acc_u, acc_t = 0;
292 gdouble err_rot, err_off, err_vel, err_acc;
293 guint32 appsecific_num; /* appdata parser should add a subtree based on this value */
294 guint32 flags=0, chars=0;
295
296 static int * const ppi_vector_present_flags[] = {
297 &hf_ppi_vector_present_vflags,
298 &hf_ppi_vector_present_vchars,
299 &hf_ppi_vector_present_val_x,
300 &hf_ppi_vector_present_val_y,
301 &hf_ppi_vector_present_val_z,
302 &hf_ppi_vector_present_off_r,
303 &hf_ppi_vector_present_off_f,
304 &hf_ppi_vector_present_off_u,
305 &hf_ppi_vector_present_vel_r,
306 &hf_ppi_vector_present_vel_f,
307 &hf_ppi_vector_present_vel_u,
308 &hf_ppi_vector_present_vel_t,
309 &hf_ppi_vector_present_acc_r,
310 &hf_ppi_vector_present_acc_f,
311 &hf_ppi_vector_present_acc_u,
312 &hf_ppi_vector_present_acc_t,
313 &hf_ppi_vector_present_err_rot,
314 &hf_ppi_vector_present_err_off,
315 &hf_ppi_vector_present_err_vel,
316 &hf_ppi_vector_present_err_acc,
317 &hf_ppi_vector_present_descstr,
318 &hf_ppi_vector_presenappsecific_num,
319 &hf_ppi_vector_present_appspecific_data,
320 &hf_ppi_vector_present_ext,
321 NULL
322 };
323
324 /* temporary, conversion values */
325 guint32 t_val;
326
327 present = tvb_get_letohl(tvb, offset+4);
328 /* Subtree for the "present flags" bitfield. */
329 pt = proto_tree_add_bitmask(ppi_vector_tree, tvb, offset + 4, hf_ppi_vector_present, ett_ppi_vector_present, ppi_vector_present_flags, ENC_LITTLE_ENDIAN);
330
331 offset += PPI_GEOBASE_MIN_HEADER_LEN;
332 length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;
333
334
335 /* Now all of the fixed length, fixed location stuff is over. Loop over the bits */
336 for (; present; present = next_present) {
337 /* clear the least significant bit that is set */
338 next_present = present & (present - 1);
339 /* extract the least significant bit that is set */
340 bit = BITNO_32(present ^ next_present);
341 switch (bit) {
342 case PPI_VECTOR_VFLAGS:
343 if (length_remaining < 4)
344 break;
345 flags = tvb_get_letohl(tvb, offset);
346 if (ppi_vector_tree) {
347 my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vflags, tvb, offset , 4, flags);
348 vectorflags_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorflags);
349
350 proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_defines_forward, tvb, offset, 4, ENC_LITTLE_ENDIAN);
351 proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_rots_absolute, tvb, offset, 4, ENC_LITTLE_ENDIAN);
352 proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_offsets_from_gps, tvb, offset, 4, ENC_LITTLE_ENDIAN);
353 }
354 offset+=4;
355 length_remaining-=4;
356 break;
357 case PPI_VECTOR_VCHARS:
358 if (length_remaining < 4)
359 break;
360 chars = tvb_get_letohl(tvb, offset);
361 if (ppi_vector_tree) {
362 my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vchars, tvb, offset , 4, chars);
363 vectorchars_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorchars);
364
365 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_antenna, tvb, offset, 4, ENC_LITTLE_ENDIAN);
366 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_dir_of_travel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
367 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_front_of_veh, tvb, offset, 4, ENC_LITTLE_ENDIAN);
368 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_gps_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
369 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_ins_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
370 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_compass_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
371 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_accelerometer_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
372 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_human_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
373 }
374 offset+=4;
375 length_remaining-=4;
376 break;
377 case PPI_VECTOR_ROTX:
378 if (length_remaining < 4)
379 break;
380 t_val = tvb_get_letohl(tvb, offset);
381 rot_x = ppi_fixed3_6_to_gdouble(t_val);
382 if (ppi_vector_tree) {
383 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_x, tvb, offset, 4, rot_x);
384 if (flags & PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
385 proto_item_append_text(ti, " Degrees (Absolute)");
386 else
387 proto_item_append_text(ti, " Degrees (Rel to forward)");
388 }
389 offset+=4;
390 length_remaining-=4;
391 break;
392 case PPI_VECTOR_ROTY:
393 if (length_remaining < 4)
394 break;
395 t_val = tvb_get_letohl(tvb, offset);
396 rot_y = ppi_fixed3_6_to_gdouble(t_val);
397 if (ppi_vector_tree) {
398 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_y, tvb, offset, 4, rot_y);
399 if (flags & PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
400 proto_item_append_text(ti, " Degrees (Absolute)");
401 else
402 proto_item_append_text(ti, " Degrees (Rel to forward)");
403 }
404 offset+=4;
405 length_remaining-=4;
406 break;
407 case PPI_VECTOR_ROTZ:
408 if (length_remaining < 4)
409 break;
410 t_val = tvb_get_letohl(tvb, offset);
411 rot_z = ppi_fixed3_6_to_gdouble(t_val);
412 if (ppi_vector_tree) {
413 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_z, tvb, offset, 4, rot_z);
414 if (flags & PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
415 proto_item_append_text(ti, " Degrees (Absolute) ");
416 else
417 proto_item_append_text(ti, " Degrees (Rel to forward)");
418 }
419 offset+=4;
420 length_remaining-=4;
421 break;
422 case PPI_VECTOR_OFF_R:
423 if (length_remaining < 4)
424 break;
425 t_val = tvb_get_letohl(tvb, offset);
426 off_r = ppi_fixed6_4_to_gdouble(t_val);
427 if (ppi_vector_tree) {
428 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_r, tvb, offset, 4, off_r);
429 if (flags & PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
430 proto_item_append_text(ti, " m from Curr_GPS");
431 else
432 proto_item_append_text(ti, " m from Curr_Pos");
433 }
434 offset+=4;
435 length_remaining-=4;
436 break;
437 case PPI_VECTOR_OFF_F:
438 if (length_remaining < 4)
439 break;
440 t_val = tvb_get_letohl(tvb, offset);
441 off_f = ppi_fixed6_4_to_gdouble(t_val);
442 if (ppi_vector_tree) {
443 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_f, tvb, offset, 4, off_f);
444 if (flags & PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
445 proto_item_append_text(ti, " m from Curr_GPS");
446 else
447 proto_item_append_text(ti, " m from Curr_Pos");
448 }
449 offset+=4;
450 length_remaining-=4;
451 break;
452 case PPI_VECTOR_OFF_U:
453 if (length_remaining < 4)
454 break;
455 t_val = tvb_get_letohl(tvb, offset);
456 off_u = ppi_fixed6_4_to_gdouble(t_val);
457 if (ppi_vector_tree) {
458 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_u, tvb, offset, 4, off_u);
459 if (flags & PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
460 proto_item_append_text(ti, " m from Curr_GPS");
461 else
462 proto_item_append_text(ti, " m from Curr_Pos");
463 }
464 offset+=4;
465 length_remaining-=4;
466 break;
467 case PPI_VECTOR_VEL_R:
468 if (length_remaining < 4)
469 break;
470 t_val = tvb_get_letohl(tvb, offset);
471 vel_r = ppi_fixed6_4_to_gdouble(t_val);
472 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_r, tvb, offset, 4, vel_r);
473 offset+=4;
474 length_remaining-=4;
475 break;
476 case PPI_VECTOR_VEL_F:
477 if (length_remaining < 4)
478 break;
479 t_val = tvb_get_letohl(tvb, offset);
480 vel_f = ppi_fixed6_4_to_gdouble(t_val);
481 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_f, tvb, offset, 4, vel_f);
482 offset+=4;
483 length_remaining-=4;
484 break;
485 case PPI_VECTOR_VEL_U:
486 if (length_remaining < 4)
487 break;
488 t_val = tvb_get_letohl(tvb, offset);
489 vel_u = ppi_fixed6_4_to_gdouble(t_val);
490 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_u, tvb, offset, 4, vel_u);
491 offset+=4;
492 length_remaining-=4;
493 break;
494 case PPI_VECTOR_VEL_T:
495 if (length_remaining < 4)
496 break;
497 t_val = tvb_get_letohl(tvb, offset);
498 vel_t = ppi_fixed6_4_to_gdouble(t_val);
499 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_t, tvb, offset, 4, vel_t);
500 offset+=4;
501 length_remaining-=4;
502 break;
503 case PPI_VECTOR_ACC_R:
504 if (length_remaining < 4)
505 break;
506 t_val = tvb_get_letohl(tvb, offset);
507 acc_r = ppi_fixed6_4_to_gdouble(t_val);
508 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_r, tvb, offset, 4, acc_r);
509 offset+=4;
510 length_remaining-=4;
511 break;
512 case PPI_VECTOR_ACC_F:
513 if (length_remaining < 4)
514 break;
515 t_val = tvb_get_letohl(tvb, offset);
516 acc_f = ppi_fixed6_4_to_gdouble(t_val);
517 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_f, tvb, offset, 4, acc_f);
518 offset+=4;
519 length_remaining-=4;
520 break;
521 case PPI_VECTOR_ACC_U:
522 if (length_remaining < 4)
523 break;
524 t_val = tvb_get_letohl(tvb, offset);
525 acc_u = ppi_fixed6_4_to_gdouble(t_val);
526 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_u, tvb, offset, 4, acc_u);
527 offset+=4;
528 length_remaining-=4;
529 break;
530 case PPI_VECTOR_ACC_T:
531 if (length_remaining < 4)
532 break;
533 t_val = tvb_get_letohl(tvb, offset);
534 acc_t = ppi_fixed6_4_to_gdouble(t_val);
535 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_t, tvb, offset, 4, acc_t);
536 offset+=4;
537 length_remaining-=4;
538 break;
539 case PPI_VECTOR_ERR_ROT:
540 if (length_remaining < 4)
541 break;
542 t_val = tvb_get_letohl(tvb, offset);
543 err_rot = ppi_fixed3_6_to_gdouble(t_val);
544 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_rot, tvb, offset, 4, err_rot);
545 offset+=4;
546 length_remaining-=4;
547 break;
548 case PPI_VECTOR_ERR_OFF:
549 if (length_remaining < 4)
550 break;
551 t_val = tvb_get_letohl(tvb, offset);
552 err_off = ppi_fixed6_4_to_gdouble(t_val);
553 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_off, tvb, offset, 4, err_off);
554 offset+=4;
555 length_remaining-=4;
556 break;
557 case PPI_VECTOR_ERR_VEL:
558 if (length_remaining < 4)
559 break;
560 t_val = tvb_get_letohl(tvb, offset);
561 err_vel = ppi_fixed6_4_to_gdouble(t_val);
562 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_vel, tvb, offset, 4, err_vel);
563 offset+=4;
564 length_remaining-=4;
565 break;
566 case PPI_VECTOR_ERR_ACC:
567 if (length_remaining < 4)
568 break;
569 t_val = tvb_get_letohl(tvb, offset);
570 err_acc = ppi_fixed6_4_to_gdouble(t_val);
571 if (ppi_vector_tree) {
572 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_acc, tvb, offset, 4, err_acc);
573 proto_item_append_text(ti, " (m/s)/s");
574 }
575 offset+=4;
576 length_remaining-=4;
577 break;
578 case PPI_VECTOR_DESCSTR:
579 if (length_remaining < 32)
580 break;
581 proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, ENC_ASCII|ENC_NA);
582 offset+=32;
583 length_remaining-=32;
584 break;
585 case PPI_VECTOR_APPID:
586 if (length_remaining < 4)
587 break;
588 appsecific_num = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
589 proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_appspecific_num, tvb, offset, 4, appsecific_num);
590 offset+=4;
591 length_remaining-=4;
592 break;
593 case PPI_VECTOR_APPDATA:
594 if (length_remaining < 60)
595 break;
596 proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_appspecific_data, tvb, offset, 60, ENC_NA);
597 offset+=60;
598 length_remaining-=60;
599 break;
600
601 default:
602 /*
603 * This indicates a field whose size we do not
604 * know, so we cannot proceed.
605 */
606 expert_add_info_format(pinfo, pt, &ei_ppi_vector_present_bit, "Error: PPI-VECTOR: unknown bit (%d) set in present field.", bit);
607 next_present = 0;
608 continue;
609 }
610
611 }
612 }
613
614 static void
dissect_ppi_vector_v2(tvbuff_t * tvb,packet_info * pinfo,int offset,gint length_remaining,proto_tree * ppi_vector_tree,proto_item * vector_line)615 dissect_ppi_vector_v2(tvbuff_t *tvb, packet_info *pinfo, int offset, gint length_remaining, proto_tree *ppi_vector_tree, proto_item *vector_line)
616 {
617 proto_tree *vectorflags_tree = NULL;
618 proto_tree *vectorchars_tree = NULL;
619 proto_tree *my_pt, *pt;
620 proto_item *ti;
621
622 /* bits */
623 int bit;
624 guint32 present, next_present;
625
626 /* values actually read out, for displaying */
627 gchar *curr_str;
628
629 /* these are used to specially handle RelativeTo: */
630 guint32 relativeto_int;
631 const gchar *relativeto_str= "RelativeTo: Forward"; /* default if vflags is not present*/
632
633 /* normal fields*/
634 guint32 flags=0, chars=0;
635 gdouble rot_x, rot_y, rot_z;
636 gdouble off_x, off_y, off_z;
637 gdouble err_rot, err_off;
638 guint32 appsecific_num; /* appdata parser should add a subtree based on this value */
639
640 static int * const ppi_vector_present_flags[] = {
641 &hf_ppi_vector_present_vflags,
642 &hf_ppi_vector_present_vchars,
643 &hf_ppi_vector_present_val_x,
644 &hf_ppi_vector_present_val_y,
645 &hf_ppi_vector_present_val_z,
646 &hf_ppi_vector_present_off_x,
647 &hf_ppi_vector_present_off_y,
648 &hf_ppi_vector_present_off_z,
649 &hf_ppi_vector_present_err_rot,
650 &hf_ppi_vector_present_err_off,
651 &hf_ppi_vector_present_descstr,
652 &hf_ppi_vector_presenappsecific_num,
653 &hf_ppi_vector_present_appspecific_data,
654 &hf_ppi_vector_present_ext,
655 NULL
656 };
657
658 /* temporary, conversion values */
659 guint32 t_val;
660
661 present = tvb_get_letohl(tvb, offset+4);
662 /* Subtree for the "present flags" bitfield. */
663 pt = proto_tree_add_bitmask(ppi_vector_tree, tvb, offset + 4, hf_ppi_vector_present, ett_ppi_vector_present, ppi_vector_present_flags, ENC_LITTLE_ENDIAN);
664
665 offset += PPI_GEOBASE_MIN_HEADER_LEN;
666 length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;
667
668 /* Before we process any fields, we check what this vector is RelativeTo. */
669 /* We do this so this up front so that it displays prominently in the summary line */
670 /* Another reason to do this up here is that vflags may not be present (in which case it defaults to 0) */
671 /* It also saves us from repeating this logic in any of the individual fields */
672 if ( (present & PPI_VECTOR_MASK_VFLAGS) && length_remaining >= 4)
673 {
674 /*vflags is the first field, */
675 flags = tvb_get_letohl(tvb, offset);
676 relativeto_int = (flags & (PPI_VECTOR_VFLAGS_RELATIVE_TO)); /* mask out all other bits */
677 relativeto_int = relativeto_int >> 1; /*scoot over 1 bit to align with the type string */
678 relativeto_str = val_to_str_const (relativeto_int, relativeto_string, "Reserved"); /*re-use that type string up top */
679 /* We will append this text to the vector line once all the other fields have processed */
680
681 /* this is important enough to put in vector line */
682 if (flags & PPI_VECTOR_VFLAGS_DEFINES_FORWARD)
683 proto_item_append_text(vector_line, " (Forward)");
684
685 /* Intentionally don't upset offset, length_remaining. This is taken care of in the normal vflags parser below*/
686 }
687 else /* No vflags means vlfags defaults to zero. RelativeTo: Forward */
688 {
689 relativeto_str = " RelativeTo: Forward";
690 }
691 /*
692 * vchars is another field that we want to pre-process similar to vflags and for the same reasons.
693 * we perform separate length checks depending on if vector_flags is present (which would precede vector_chars)
694 */
695 if ( ( (present & PPI_VECTOR_MASK_VFLAGS)) && (present & PPI_VECTOR_MASK_VCHARS) && length_remaining >= 8)
696 chars = tvb_get_letohl(tvb, offset + 4);
697 else if ( (!(present & PPI_VECTOR_MASK_VFLAGS)) && (present & PPI_VECTOR_MASK_VCHARS) && length_remaining >= 4)
698 chars = tvb_get_letohl(tvb, offset );
699
700 if (chars)
701 {
702 /* Mark the most interesting characteristics on the vector dropdown line */
703 annotate_vector_chars(chars, vector_line);
704 /* Intentionally don't update offset, length_remaining. This is taken care of in the normal vchars parser below*/
705 }
706
707 /* Now all of the fixed length, fixed location stuff is over. Loop over the bits */
708 for (; present; present = next_present) {
709 /* clear the least significant bit that is set */
710 next_present = present & (present - 1);
711 /* extract the least significant bit that is set */
712 bit = BITNO_32(present ^ next_present);
713 switch (bit) {
714 case PPI_VECTOR_VFLAGS:
715 if (length_remaining < 4)
716 break;
717 /* flags = tvb_get_letohl(tvb, offset); */ /* Usually we read this in, but vflags is a special case handled above */
718 if (ppi_vector_tree) {
719 my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vflags, tvb, offset , 4, flags);
720 vectorflags_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorflags);
721
722 proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_defines_forward, tvb, offset, 4, ENC_LITTLE_ENDIAN);
723 proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_relative_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
724
725 if (flags & PPI_VECTOR_VFLAGS_DEFINES_FORWARD)
726 proto_item_append_text(vectorflags_tree, " (Forward)");
727
728 proto_item_append_text (vectorflags_tree, " RelativeTo: %s", relativeto_str);
729 }
730 offset+=4;
731 length_remaining-=4;
732 break;
733 case PPI_VECTOR_VCHARS:
734 if (length_remaining < 4)
735 break;
736 /* chars = tvb_get_letohl(tvb, offset); */ /*Usually we read this in, but vchars specially handled above */
737 if (ppi_vector_tree) {
738 my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vchars, tvb, offset , 4, chars);
739 vectorchars_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorchars);
740
741 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_antenna, tvb, offset, 4, ENC_LITTLE_ENDIAN);
742 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_dir_of_travel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
743 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_front_of_veh, tvb, offset, 4, ENC_LITTLE_ENDIAN);
744 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_angle_of_arrival, tvb, offset, 4, ENC_LITTLE_ENDIAN);
745 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_transmitter_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
746 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_gps_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
747 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_ins_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
748 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_compass_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
749 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_accelerometer_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
750 proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_human_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN);
751
752 annotate_vector_chars(chars, my_pt);
753 }
754 offset+=4;
755 length_remaining-=4;
756 break;
757 case PPI_VECTOR_ROTX:
758 if (length_remaining < 4)
759 break;
760 t_val = tvb_get_letohl(tvb, offset);
761 rot_x = ppi_fixed3_6_to_gdouble(t_val);
762 if (ppi_vector_tree) {
763 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_x, tvb, offset, 4, rot_x);
764 proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str);
765 proto_item_append_text(vector_line, " Pitch:%3f ", rot_x);
766 }
767 offset+=4;
768 length_remaining-=4;
769 break;
770 case PPI_VECTOR_ROTY:
771 if (length_remaining < 4)
772 break;
773 t_val = tvb_get_letohl(tvb, offset);
774 rot_y = ppi_fixed3_6_to_gdouble(t_val);
775 if (ppi_vector_tree) {
776 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_y, tvb, offset, 4, rot_y);
777 proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str);
778 proto_item_append_text(vector_line, " Roll:%3f ", rot_y);
779 }
780 offset+=4;
781 length_remaining-=4;
782 break;
783 case PPI_VECTOR_ROTZ:
784 if (length_remaining < 4)
785 break;
786 t_val = tvb_get_letohl(tvb, offset);
787 rot_z = ppi_fixed3_6_to_gdouble(t_val);
788 if (ppi_vector_tree) {
789 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_z, tvb, offset, 4, rot_z);
790 proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str);
791 proto_item_append_text(vector_line, " Heading:%3f ", rot_z);
792 }
793 offset+=4;
794 length_remaining-=4;
795 break;
796 case PPI_VECTOR_OFF_X:
797 if (length_remaining < 4)
798 break;
799 t_val = tvb_get_letohl(tvb, offset);
800 off_x = ppi_fixed6_4_to_gdouble(t_val);
801 if (ppi_vector_tree) {
802 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_x, tvb, offset, 4, off_x);
803 proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str);
804 proto_item_append_text(vector_line, " Off-X:%3f ", off_x);
805 }
806 offset+=4;
807 length_remaining-=4;
808 break;
809 case PPI_VECTOR_OFF_Y:
810 if (length_remaining < 4)
811 break;
812 t_val = tvb_get_letohl(tvb, offset);
813 off_y = ppi_fixed6_4_to_gdouble(t_val);
814 if (ppi_vector_tree) {
815 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_y, tvb, offset, 4, off_y);
816 proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str);
817 proto_item_append_text(vector_line, " Off-Y:%3f ", off_y);
818 }
819 offset+=4;
820 length_remaining-=4;
821 break;
822 case PPI_VECTOR_OFF_Z:
823 if (length_remaining < 4)
824 break;
825 t_val = tvb_get_letohl(tvb, offset);
826 off_z = ppi_fixed6_4_to_gdouble(t_val);
827 if (ppi_vector_tree) {
828 ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_z, tvb, offset, 4, off_z);
829 proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str);
830 proto_item_append_text(vector_line, " Off-Z:%3f ", off_z);
831 }
832 offset+=4;
833 length_remaining-=4;
834 break;
835 case PPI_VECTOR_ERR_ROT:
836 if (length_remaining < 4)
837 break;
838 t_val = tvb_get_letohl(tvb, offset);
839 err_rot = ppi_fixed3_6_to_gdouble(t_val);
840 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_rot, tvb, offset, 4, err_rot);
841 offset+=4;
842 length_remaining-=4;
843 break;
844 case PPI_VECTOR_ERR_OFF:
845 if (length_remaining < 4)
846 break;
847 t_val = tvb_get_letohl(tvb, offset);
848 err_off = ppi_fixed6_4_to_gdouble(t_val);
849 proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_off, tvb, offset, 4, err_off);
850 offset+=4;
851 length_remaining-=4;
852 break;
853
854 case PPI_VECTOR_DESCSTR:
855 if (length_remaining < 32)
856 break;
857 if (ppi_vector_tree)
858 {
859 /* proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, ENC_ASCII|ENC_NA); */
860 curr_str = tvb_format_stringzpad(pinfo->pool, tvb, offset, 32); /* need to append_text this */
861 proto_tree_add_string(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, curr_str);
862 proto_item_append_text(vector_line, " (%s)", curr_str);
863 }
864 offset+=32;
865 length_remaining-=32;
866 break;
867 case PPI_VECTOR_APPID:
868 if (length_remaining < 4)
869 break;
870 appsecific_num = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
871 if (ppi_vector_tree) {
872 proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_appspecific_num, tvb, offset, 4, appsecific_num);
873 }
874 offset+=4;
875 length_remaining-=4;
876 break;
877 case PPI_VECTOR_APPDATA:
878 if (length_remaining < 60)
879 break;
880 if (ppi_vector_tree) {
881 proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_appspecific_data, tvb, offset, 60, ENC_NA);
882 }
883 offset+=60;
884 length_remaining-=60;
885 break;
886
887 default:
888 /*
889 * This indicates a field whose size we do not
890 * know, so we cannot proceed.
891 */
892 expert_add_info_format(pinfo, pt, &ei_ppi_vector_present_bit, "Error: PPI-VECTOR: unknown bit (%d) set in present field.\n", bit);
893 next_present = 0;
894 continue;
895 }
896 }
897 /* Append the RelativeTo string we computed up top */
898 proto_item_append_text (vector_line, " RelativeTo: %s", relativeto_str);
899 }
900
901 static int
dissect_ppi_vector(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)902 dissect_ppi_vector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
903 {
904 proto_tree *ppi_vector_tree;
905 proto_item *ti, *vector_line;
906 gint length_remaining;
907 int offset = 0;
908
909 /* values actually read out, for displaying */
910 guint32 version;
911 guint length;
912
913 /* Clear out stuff in the info column */
914 col_clear(pinfo->cinfo,COL_INFO);
915
916 /* pull out the first three fields of the BASE-GEOTAG-HEADER */
917 version = tvb_get_guint8(tvb, offset);
918 length = tvb_get_letohs(tvb, offset+2);
919
920 /* Setup basic column info */
921 col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_Vector Capture v%u, Length %u",
922 version, length);
923
924 /* Create the basic dissection tree*/
925 vector_line = proto_tree_add_protocol_format(tree, proto_ppi_vector, tvb, 0, length, "Vector:");
926 ppi_vector_tree = proto_item_add_subtree(vector_line, ett_ppi_vector);
927 proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_version,
928 tvb, offset, 1, version);
929 proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_pad,
930 tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
931 ti = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_length,
932 tvb, offset + 2, 2, length);
933
934 /* initialize remaining length */
935 length_remaining = length;
936 /* minimum length check, should atleast be a fixed-size geotagging-base header*/
937 if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
938 /*
939 * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion
940 * plus one "present" bitset.
941 */
942 expert_add_info_format(pinfo, ti, &ei_ppi_vector_length, "Invalid PPI-Vector length - minimum length is %d", PPI_GEOBASE_MIN_HEADER_LEN);
943 return 2;
944 }
945
946 switch (version) {
947
948 case 1:
949 dissect_ppi_vector_v1(tvb, pinfo, offset, length_remaining, ppi_vector_tree);
950 break;
951
952 case 2:
953 /* perform max length sanity checking */
954 if (length > PPI_VECTOR_MAXTAGLEN ) {
955 expert_add_info_format(pinfo, ti, &ei_ppi_vector_length, "Invalid PPI-Vector length (got %d, %d max\n)", length, PPI_VECTOR_MAXTAGLEN);
956 return 2;
957 }
958 dissect_ppi_vector_v2(tvb, pinfo, offset, length_remaining, ppi_vector_tree, vector_line);
959 break;
960
961 default:
962 proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_unknown_data, tvb, offset + 4, -1, ENC_NA);
963 break;
964 }
965 return tvb_captured_length(tvb);
966 }
967
968 void
proto_register_ppi_vector(void)969 proto_register_ppi_vector(void)
970 {
971 /* The following array initializes those header fields declared above to the values displayed */
972 static hf_register_info hf[] = {
973 { &hf_ppi_vector_version,
974 { "Header revision", "ppi_vector.version",
975 FT_UINT8, BASE_DEC, NULL, 0x0,
976 "Version of ppi_vector header format", HFILL } },
977 { &hf_ppi_vector_pad,
978 { "Header pad", "ppi_vector.pad",
979 FT_UINT8, BASE_DEC, NULL, 0x0,
980 "Padding", HFILL } },
981 { &hf_ppi_vector_length,
982 { "Header length", "ppi_vector.length",
983 FT_UINT16, BASE_DEC, NULL, 0x0,
984 "Length of header including version, pad, length and data fields", HFILL } },
985 { &hf_ppi_vector_present,
986 { "Present", "ppi_vector.present",
987 FT_UINT32, BASE_HEX, NULL, 0x0,
988 "Bitmask indicating which fields are present", HFILL } },
989
990 /* Boolean 'present' flags */
991 { &hf_ppi_vector_present_vflags,
992 { "Vector flags", "ppi_vector.present.flags",
993 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VFLAGS,
994 "Specifies if the Vector flags bitfield is present", HFILL } },
995
996 { &hf_ppi_vector_present_vchars,
997 { "Vector characteristics", "ppi_vector.present.chars",
998 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VCHARS,
999 "Specifies if the Vector chars bitfield is present", HFILL } },
1000
1001 { &hf_ppi_vector_present_val_x,
1002 { "Pitch", "ppi_vector.present.pitch",
1003 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTX,
1004 "Specifies if the rotate-x field (pitch) is present", HFILL } },
1005
1006 { &hf_ppi_vector_present_val_y,
1007 { "Roll", "ppi_vector.present.roll",
1008 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTY,
1009 "Specifies if the rotate-y field (roll) is present", HFILL } },
1010
1011 { &hf_ppi_vector_present_val_z,
1012 { "Heading", "ppi_vector.present.heading",
1013 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTZ,
1014 "Specifies if the rotate-z field (heading) is present", HFILL } },
1015
1016
1017 /* V1 */
1018 { &hf_ppi_vector_present_off_r,
1019 { "Offset_R", "ppi_vector.present.off_r",
1020 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_R,
1021 "Specifies if the offset-right field is present", HFILL } },
1022
1023 { &hf_ppi_vector_present_off_f,
1024 { "Offset_F", "ppi_vector.present.off_f",
1025 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_F,
1026 "Specifies if the offset-forward field is present", HFILL } },
1027
1028 { &hf_ppi_vector_present_off_u,
1029 { "Offset_U", "ppi_vector.present.off_u",
1030 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_U,
1031 "Specifies if the offset-up field is present", HFILL } },
1032
1033 { &hf_ppi_vector_present_vel_r,
1034 { "Velocity_R", "ppi_vector.present.vel_r",
1035 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_R,
1036 "Specifies if the velocity-right field is present", HFILL } },
1037
1038 { &hf_ppi_vector_present_vel_f,
1039 { "Velocity_F", "ppi_vector.present.vel_f",
1040 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_F,
1041 "Specifies if the velocity-forward field is present", HFILL } },
1042
1043 { &hf_ppi_vector_present_vel_u,
1044 { "Velocity_U", "ppi_vector.present.vel_u",
1045 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_U,
1046 "Specifies if the velocity-up field is present", HFILL } },
1047 { &hf_ppi_vector_present_vel_t,
1048 { "Velocity_T", "ppi_vector.present.vel_t",
1049 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_T,
1050 "Specifies if the total velocity field is present", HFILL } },
1051
1052 { &hf_ppi_vector_present_acc_r,
1053 { "Acceleration_R", "ppi_vector.present.acc_r",
1054 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_R,
1055 "Specifies if the accel-right field is present", HFILL } },
1056
1057 { &hf_ppi_vector_present_acc_f,
1058 { "Acceleration_F", "ppi_vector.present.acc_f",
1059 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_F,
1060 "Specifies if the accel-forward field is present", HFILL } },
1061
1062 { &hf_ppi_vector_present_acc_u,
1063 { "Acceleration_U", "ppi_vector.present.acc_u",
1064 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_U,
1065 "Specifies if the accel-up field is present", HFILL } },
1066 { &hf_ppi_vector_present_acc_t,
1067 { "Acceleration_T", "ppi_vector.present.acc_t",
1068 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_T,
1069 "Specifies if the total acceleration field is present", HFILL } },
1070
1071 /* V2 */
1072 { &hf_ppi_vector_present_off_x,
1073 { "Offset_R", "ppi_vector.present.off_x",
1074 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_X,
1075 "Specifies if the offset-x (right/east) field is present", HFILL } },
1076
1077 { &hf_ppi_vector_present_off_y,
1078 { "Offset_F", "ppi_vector.present.off_y",
1079 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_Y,
1080 "Specifies if the offset-y (forward/north) field is present", HFILL } },
1081
1082 { &hf_ppi_vector_present_off_z,
1083 { "Offset_U", "ppi_vector.present.off_z",
1084 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_Z,
1085 "Specifies if the offset-z (up) field is present", HFILL } },
1086
1087
1088 { &hf_ppi_vector_present_err_rot,
1089 { "err_rot", "ppi_vector.present.err_rot",
1090 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_ROT,
1091 "Specifies if the rotation error field is present", HFILL } },
1092
1093 { &hf_ppi_vector_present_err_off,
1094 { "err_off", "ppi_vector.present.err_off",
1095 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_OFF,
1096 "Specifies if the offset error field is present", HFILL } },
1097
1098
1099 /* V1 only */
1100 { &hf_ppi_vector_present_err_vel,
1101 { "err_vel", "ppi_vector.present.err_vel",
1102 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_VEL,
1103 "Specifies if the velocity error field is present", HFILL } },
1104
1105 { &hf_ppi_vector_present_err_acc,
1106 { "err_acc", "ppi_vector.present.err_acc",
1107 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_ACC,
1108 "Specifies if the acceleration error field is present", HFILL } },
1109
1110
1111 { &hf_ppi_vector_present_descstr,
1112 { "descstr", "ppi_vector.present.descstr",
1113 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_DESCSTR,
1114 "Specifies if the acceleration error field is present", HFILL } },
1115
1116 { &hf_ppi_vector_presenappsecific_num,
1117 { "appid", "ppi_vector.present.appid",
1118 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_APPID,
1119 "Specifies if the application specific field id is present", HFILL } },
1120
1121 { &hf_ppi_vector_present_appspecific_data,
1122 { "appdata", "ppi_vector.present.appdata",
1123 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_APPDATA,
1124 "Specifies if the application specific data field is present", HFILL } },
1125
1126 { &hf_ppi_vector_present_ext,
1127 { "Ext", "ppi_vector.present.ext",
1128 FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_EXT,
1129 "Specifies if there are any extensions to the header present", HFILL } },
1130
1131 /* Now we get to the actual data fields */
1132 /* This setups the "Vector fflags" hex dropydown thing */
1133 { &hf_ppi_vector_vflags,
1134 { "Vector flags", "ppi_vector.vector_flags",
1135 FT_UINT32, BASE_HEX, NULL, 0x0,
1136 "Bitmask indicating coordinate sys, among others, etc", HFILL } },
1137 { &hf_ppi_vector_vchars,
1138 { "Vector chars", "ppi_vector.vector_chars",
1139 FT_UINT32, BASE_HEX, NULL, 0x0,
1140 "Bitmask indicating if vector tracks antenna, vehicle, motion, etc", HFILL } },
1141 { &hf_ppi_vector_rot_x,
1142 { "Pitch", "ppi_vector.pitch",
1143 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1144 "Pitch (Rotation x) packet was received at", HFILL } },
1145 { &hf_ppi_vector_rot_y,
1146 { "Roll", "ppi_vector.roll",
1147 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1148 "Roll (Rotation y) packet was received at", HFILL } },
1149 { &hf_ppi_vector_rot_z,
1150 { "Heading", "ppi_vector.heading",
1151 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1152 "Heading (Rotation z) packet was received at", HFILL } },
1153
1154 /* V1 */
1155 { &hf_ppi_vector_off_r,
1156 { "Off-r", "ppi_vector.off_r",
1157 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1158 "Offset right", HFILL } },
1159 { &hf_ppi_vector_off_f,
1160 { "Off-f", "ppi_vector.off_f",
1161 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1162 "Offation forward", HFILL } },
1163 { &hf_ppi_vector_off_u,
1164 { "Off-u", "ppi_vector.off_u",
1165 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1166 "Offset up", HFILL } },
1167 { &hf_ppi_vector_vel_r,
1168 { "Vel-r", "ppi_vector.vel_r",
1169 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec, 0x0,
1170 "Velocity-right", HFILL } },
1171 { &hf_ppi_vector_vel_f,
1172 { "Vel-f", "ppi_vector.vel_f",
1173 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec, 0x0,
1174 "Velocity-forward", HFILL } },
1175 { &hf_ppi_vector_vel_u,
1176 { "Vel-u", "ppi_vector.vel_u",
1177 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec, 0x0,
1178 "Velocity-up", HFILL } },
1179 { &hf_ppi_vector_vel_t,
1180 { "Vel-t", "ppi_vector.vel_t",
1181 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec, 0x0,
1182 "Velocity-Total", HFILL } },
1183
1184 { &hf_ppi_vector_acc_r,
1185 { "Accel-r", "ppi_vector.acc_r",
1186 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec_squared, 0x0,
1187 "Acceleration-right", HFILL } },
1188 { &hf_ppi_vector_acc_f,
1189 { "Accel-f", "ppi_vector.acc_f",
1190 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec_squared, 0x0,
1191 "Acceleration-forward", HFILL } },
1192 { &hf_ppi_vector_acc_u,
1193 { "Accel-u", "ppi_vector.acc_u",
1194 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec_squared, 0x0,
1195 "Acceleration-up", HFILL } },
1196 { &hf_ppi_vector_acc_t,
1197 { "Accel-t", "ppi_vector.acc_t",
1198 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec_squared, 0x0,
1199 "Acceleration-Total", HFILL } },
1200
1201 /* V2 */
1202 { &hf_ppi_vector_off_x,
1203 { "Off-x", "ppi_vector.off_x",
1204 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1205 "Offset-x (right/east)", HFILL } },
1206 { &hf_ppi_vector_off_y,
1207 { "Off-y", "ppi_vector.off_y",
1208 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1209 "Offset-y (forward/north)", HFILL } },
1210 { &hf_ppi_vector_off_z,
1211 { "Off-z", "ppi_vector.off_z",
1212 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1213 "Offset-z (up)", HFILL } },
1214
1215 { &hf_ppi_vector_err_rot,
1216 { "Err-Rot", "ppi_vector.err_rot",
1217 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_degree_degrees, 0x0,
1218 "Rotation margin of error", HFILL } },
1219 { &hf_ppi_vector_err_off,
1220 { "Err-Off", "ppi_vector.err_off",
1221 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_meters, 0x0,
1222 "Offset margin of error", HFILL } },
1223
1224 /* V1 only */
1225 { &hf_ppi_vector_err_vel,
1226 { "Err-Vel", "ppi_vector.err_vel",
1227 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec, 0x0,
1228 "Velocity margin of error", HFILL } },
1229 { &hf_ppi_vector_err_acc,
1230 { "Err-Accel", "ppi_vector.err_acc",
1231 FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_sec_squared, 0x0,
1232 "Acceleration margin of error", HFILL } },
1233
1234 { &hf_ppi_vector_descstr,
1235 { "Description", "ppi_vector.descr",
1236 FT_STRING, BASE_NONE, NULL, 0x0,
1237 NULL, HFILL } } ,
1238 { &hf_ppi_vector_appspecific_num,
1239 { "Application Specific id", "ppi_vector.appid",
1240 FT_UINT32, BASE_HEX, NULL, 0x0,
1241 "Application-specific identifier", HFILL } },
1242 { &hf_ppi_vector_appspecific_data,
1243 { "Application specific data", "ppi_vector.appdata",
1244 FT_BYTES, BASE_NONE, NULL, 0x0,
1245 "Application-specific data", HFILL } },
1246
1247 /* Boolean vector flags */
1248 { &hf_ppi_vector_vflags_defines_forward,
1249 { "Defines forward", "ppi_vector.vflags.forward",
1250 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_DEFINES_FORWARD,
1251 "Current vector indicates forward frame of reference", HFILL } },
1252
1253 /* V1 */
1254 { &hf_ppi_vector_vflags_rots_absolute,
1255 { "Absolute (E/N/U) rotations", "ppi_vector.vflags.abs_rots",
1256 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE,
1257 "Rotations are in East/North/Up coord. sys", HFILL } },
1258 { &hf_ppi_vector_vflags_offsets_from_gps,
1259 { "Offsets from prev GPS TAG", "ppi_vector.vflags.offsets_from_gps",
1260 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS,
1261 "Offsets fied rel. to Curr_Gps", HFILL } },
1262
1263 /* V2 */
1264 { &hf_ppi_vector_vflags_relative_to,
1265 { "RelativeTo", "ppi_vector.vflags.relative_to", FT_UINT32, BASE_HEX, VALS(relativeto_string), PPI_VECTOR_VFLAGS_RELATIVE_TO,
1266 "Reference frame vectors are RelativeTo:", HFILL } },
1267
1268 /* Boolean vector chars */
1269 { &hf_ppi_vector_vchars_antenna,
1270 { "Antenna", "ppi_vector.chars.antenna",
1271 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_ANTENNA,
1272 "Vector represents: Antenna", HFILL } },
1273
1274 { &hf_ppi_vector_vchars_dir_of_travel,
1275 { "Dir of travel", "ppi_vector.chars.dir_of_travel",
1276 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_DIR_OF_TRAVEL,
1277 "Vector represents: Direction of travel", HFILL } },
1278
1279 { &hf_ppi_vector_vchars_front_of_veh,
1280 { "Front of vehicle", "ppi_vector.chars.front_of_veh",
1281 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_FRONT_OF_VEH,
1282 "Vector represents: Front of vehicle", HFILL } },
1283
1284 /* V2 only */
1285 { &hf_ppi_vector_vchars_angle_of_arrival,
1286 { "Angle of arrival", "ppi_vector.chars.angle_of_arr",
1287 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_AOA,
1288 "Vector represents: Angle of Arrival", HFILL } },
1289 { &hf_ppi_vector_vchars_transmitter_pos,
1290 { "Transmitter Position", "ppi_vector.chars.transmitter_pos",
1291 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_TRANSMITTER_POS,
1292 "Vector position represents computed transmitter location", HFILL } },
1293
1294 { &hf_ppi_vector_vchars_gps_derived,
1295 { "GPS Derived", "ppi_vector.vflags.gps_derived",
1296 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_GPS_DERIVED,
1297 "Vector derived from: gps", HFILL } },
1298
1299 { &hf_ppi_vector_vchars_ins_derived,
1300 { "INS Derived", "ppi_vector.vflags.ins_derived",
1301 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_INS_DERIVED,
1302 "Vector derived from: inertial nav system", HFILL } },
1303
1304 { &hf_ppi_vector_vchars_compass_derived,
1305 { "Compass derived", "ppi_vector.vflags.compass_derived",
1306 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_COMPASS_DERIVED,
1307 "Vector derived from: compass", HFILL } },
1308
1309 { &hf_ppi_vector_vchars_accelerometer_derived,
1310 { "Accelerometer derived", "ppi_vector.vflags.accelerometer_derived",
1311 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_ACCELEROMETER_DERIVED,
1312 "Vector derived from: accelerometer", HFILL } },
1313
1314 { &hf_ppi_vector_vchars_human_derived,
1315 { "Human derived", "ppi_vector.vflags.human_derived",
1316 FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_HUMAN_DERIVED,
1317 "Vector derived from: human", HFILL } },
1318
1319 { &hf_ppi_vector_unknown_data,
1320 { "Data for unknown version", "ppi_vector.unknown_data",
1321 FT_BYTES, BASE_NONE, NULL, 0x0,
1322 NULL, HFILL } },
1323
1324 };
1325 static gint *ett[] = {
1326 &ett_ppi_vector,
1327 &ett_ppi_vector_present,
1328 &ett_ppi_vectorflags,
1329 &ett_ppi_vectorchars
1330 };
1331
1332 static ei_register_info ei[] = {
1333 { &ei_ppi_vector_present_bit, { "ppi_vector.present.unknown_bit", PI_PROTOCOL, PI_WARN, "Error: PPI-VECTOR: unknown bit set in present field.", EXPFILL }},
1334 { &ei_ppi_vector_length, { "ppi_vector.length.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
1335 };
1336
1337 expert_module_t* expert_ppi_vector;
1338
1339 proto_ppi_vector = proto_register_protocol("PPI vector decoder", "PPI vector Decoder", "ppi_vector");
1340 proto_register_field_array(proto_ppi_vector, hf, array_length(hf));
1341 proto_register_subtree_array(ett, array_length(ett));
1342 expert_ppi_vector = expert_register_protocol(proto_ppi_vector);
1343 expert_register_field_array(expert_ppi_vector, ei, array_length(ei));
1344 register_dissector("ppi_vector", dissect_ppi_vector, proto_ppi_vector);
1345
1346 }
1347
1348 /*
1349 * Editor modelines
1350 *
1351 * Local Variables:
1352 * c-basic-offset: 4
1353 * tab-width: 8
1354 * indent-tabs-mode: nil
1355 * End:
1356 *
1357 * ex: set shiftwidth=4 tabstop=8 expandtab:
1358 * :indentSize=4:tabSize=8:noTabs=true:
1359 */
1360
1361
1362