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