From Jon Ellch via bug #5175: Add PPI-GPS protocol dissector patch
authorsfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 18 Nov 2010 20:54:14 +0000 (20:54 +0000)
committersfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 18 Nov 2010 20:54:14 +0000 (20:54 +0000)
Minor changes by me as detailed in the bug's comment #8.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@34956 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/Makefile.common
epan/dissectors/packet-ppi-antenna.c [new file with mode: 0644]
epan/dissectors/packet-ppi-geolocation-common.c [new file with mode: 0644]
epan/dissectors/packet-ppi-geolocation-common.h [new file with mode: 0644]
epan/dissectors/packet-ppi-gps.c [new file with mode: 0644]
epan/dissectors/packet-ppi-vector.c [new file with mode: 0644]
epan/dissectors/packet-ppi.c

diff --git a/AUTHORS b/AUTHORS
index a05e9de050cebec0a540bf11cb00123ab1432f1a..fce2e30503a255eab213798a72378d7768e9bcb0 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3375,6 +3375,7 @@ Markus Renz               <Markus.Renz [AT] hirschmann.de>
 Toshihiro Kataoka      <kataoka.toshihiro [AT] gmail.com>
 Petr Lautrbach         <plautrba [AT] redhat.com>
 Frank Lahm             <franklahm [AT] googlemail.com>
+Jon Ellch              <jellch [AT] harris.com>
 
 Dan Lasley <dlasley[AT]promus.com> gave permission for his
 dumpit() hex-dump routine to be used.
index 8573a267a2acc443cbcd96d14aead4a0f17b2561..1c1e60b2bbf0ccafbda343ab49a586c0b3e09760 100644 (file)
@@ -750,6 +750,10 @@ DISSECTOR_SRC = \
        packet-portmap.c        \
        packet-pgsql.c          \
        packet-ppi.c            \
+       packet-ppi-antenna.c    \
+       packet-ppi-geolocation-common.c \
+       packet-ppi-gps.c        \
+       packet-ppi-vector.c     \
        packet-ppp.c            \
        packet-pppoe.c          \
        packet-pptp.c           \
@@ -1208,6 +1212,7 @@ DISSECTOR_INCLUDES =      \
        packet-pktc.h   \
        packet-portmap.h        \
        packet-ppi.h            \
+       packet-ppi-geolocation-common.h         \
        packet-ppp.h    \
        packet-pres.h   \
        packet-pw-atm.h         \
diff --git a/epan/dissectors/packet-ppi-antenna.c b/epan/dissectors/packet-ppi-antenna.c
new file mode 100644 (file)
index 0000000..0e476f6
--- /dev/null
@@ -0,0 +1,535 @@
+/* packet-ppi-antenna.c
+ * Routines for PPI-GEOLOCATION-ANNTENNA  dissection
+ * Copyright 2010, Harris Corp, jellch@harris.com
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-radiotap.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include <epan/ptvcursor.h>
+#include <epan/prefs.h>
+#include <epan/reassemble.h>
+#include <epan/dissectors/packet-ppi-geolocation-common.h>
+
+enum ppi_antenna_type {
+    PPI_ANTENNA_ANTFLAGS    = 0, /* Various flags about the antenna in use, Polarity, etc */
+    PPI_ANTENNA_GAINDB      = 1, /* Antenna gain, in dBi */
+    PPI_ANTENNA_HORIZBW     = 2, /* Antenna beamwidth, horizontal */
+    PPI_ANTENNA_VERTBW      = 3, /* Antenna beamwidth, vertical */
+    PPI_ANTENNA_PGAIN       = 4, /* precision gain */
+    PPI_ANTENNA_BEAMID      = 5, /* beam identifier (electrically steerable only) */
+    PPI_ANTENNA_RES6        = 6,
+    PPI_ANTENNA_RES7        = 7,
+    PPI_ANTENNA_SERIALNUM   = 26,
+    PPI_ANTENNA_MODELSTR    = 27, /*32 bytes, fixed length, null terminated model of antenna */
+    PPI_ANTENNA_DESCSTR     = 28, /*32 bytes, fixed length, null terminated description of what the antenna is for */
+    PPI_ANTENNA_APPID       = 29, /*4-byte identifer*/
+    PPI_ANTENNA_APPDATA     = 30, /* 60-byte app-id specific data*/
+    PPI_ANTENNA_EXT         = 31  /* Indicates n extended bitmap follows */
+};
+
+
+
+/* protocol */
+static int proto_ppi_antenna = -1;
+
+static int hf_ppi_antenna_version = -1;
+static int hf_ppi_antenna_pad = -1;
+static int hf_ppi_antenna_length = -1;
+static int hf_ppi_antenna_present = -1;
+static int hf_ppi_antenna_flags = -1;
+static int hf_ppi_antenna_gaindb = -1;
+static int hf_ppi_antenna_horizbw = -1;
+static int hf_ppi_antenna_vertbw = -1;
+static int hf_ppi_antenna_pgain= -1;
+static int hf_ppi_antenna_beamid= -1;
+static int hf_ppi_antenna_serialnum= -1;
+static int hf_ppi_antenna_modelname = -1;
+static int hf_ppi_antenna_descstr = -1;
+static int hf_ppi_antenna_appspecific_num = -1; /* 4-byte tag no */
+static int hf_ppi_antenna_appspecific_data = -1; /* 60 byte arbitrary data */
+
+
+/* "Present" flags */
+/* These represent decoded-bits in the gui */
+static int hf_ppi_antenna_present_flags= -1;
+static int hf_ppi_antenna_present_gaindb = -1;
+static int hf_ppi_antenna_present_horizbw = -1;
+static int hf_ppi_antenna_present_vertbw= -1;
+static int hf_ppi_antenna_present_pgain= -1;
+static int hf_ppi_antenna_present_beamid= -1;
+static int hf_ppi_antenna_present_serialnum= -1;
+static int hf_ppi_antenna_present_modelname = -1;
+static int hf_ppi_antenna_present_descstr = -1;
+static int hf_ppi_antenna_present_appspecific_num = -1;
+static int hf_ppi_antenna_present_appspecific_data = -1;
+static int hf_ppi_antenna_present_ext = -1;
+
+/*These are the few defined AntennaFlags bits*/
+static int hf_ppi_antennaflags_mimo= -1;
+static int hf_ppi_antennaflags_horizpol= -1;
+static int hf_ppi_antennaflags_vertpol= -1;
+static int hf_ppi_antennaflags_circpol_l= -1;
+static int hf_ppi_antennaflags_circpol_r= -1;
+static int hf_ppi_antennaflags_steer_elec= -1;
+static int hf_ppi_antennaflags_steer_mech= -1;
+
+/* These represent arrow-dropdownthings in the gui */
+static gint ett_ppi_antenna = -1;
+static gint ett_ppi_antenna_present = -1;
+static gint ett_ppi_antennaflags= -1;
+
+
+static void
+dissect_ppi_antenna(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+proto_register_ppi_antenna(void) {
+    /* The following array initializes those header fields declared above to the values displayed */
+    static hf_register_info hf[] = {
+        { &hf_ppi_antenna_version,
+            { "Header revision", "ppi_antenna.version",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Version of ppi_antenna header format", HFILL } },
+        { &hf_ppi_antenna_pad,
+          { "Header pad", "ppi_antenna.pad",
+            FT_UINT8, BASE_DEC, NULL, 0x0,
+            "Padding", HFILL } },
+        { &hf_ppi_antenna_length,
+          { "Header length", "ppi_antenna.length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of header including version, pad, length and data fields", HFILL } },
+        /* This setups the "Antenna flags" hex dropydown thing */
+        { &hf_ppi_antenna_flags,
+          { "Antenna flags", "ppi_antenna.antenna_flags",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating polarity, etc", HFILL } },
+        { &hf_ppi_antenna_present,
+          { "Present", "ppi_antenna.present",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating which fields are present", HFILL } },
+
+        /* This first set is for the base_tag_header.it_present bitfield */
+#define PPI_ANTENNA_MASK_FLAGS      0x00000001  /* 0 */
+#define PPI_ANTENNA_MASK_GAINDB     0x00000002  /* 1 */
+#define PPI_ANTENNA_MASK_HORIZBW    0x00000004  /* 2 */
+#define PPI_ANTENNA_MASK_VERTBW     0x00000008  /* 3 */
+#define PPI_ANTENNA_MASK_PGAIN      0x00000020  /* 5 */
+#define PPI_ANTENNA_MASK_BEAMID     0x00000040  /* 6 */
+#define PPI_ANTENNA_MASK_RES7       0x00000080  /* 7 */
+#define PPI_ANTENNA_MASK_SERIALNUM  0x04000000  /* 26 */
+#define PPI_ANTENNA_MASK_MODELSTR   0x08000000  /* 27 */
+#define PPI_ANTENNA_MASK_DESCSTR    0x10000000  /* 28 */
+#define PPI_ANTENNA_MASK_APPID      0x20000000  /* 29 */
+#define PPI_ANTENNA_MASK_APPDATA     0x40000000  /* 30 */
+#define PPI_ANTENNA_MASK_EXT        0x80000000  /* 31 */
+
+        /*This second set is for the AntennaFlags bitfield. */
+#define PPI_ANTENNAFLAGS_MASK_MIMO              0x00000001  /* 0 */
+#define PPI_ANTENNAFLAGS_MASK_HPOL              0x00000002  /* 1 */
+#define PPI_ANTENNAFLAGS_MASK_VPOL              0x00000004  /* 2 */
+#define PPI_ANTENNAFLAGS_MASK_CPOL_L            0x00000008  /* 3 */
+#define PPI_ANTENNAFLAGS_MASK_CPOL_R            0x00000010  /* 4 */
+#define PPI_ANTENNAFLAGS_MASK_STEER_ELEC        0x00010000  /* 16 */
+#define PPI_ANTENNAFLAGS_MASK_STEER_MECH        0x00020000  /* 17 */
+
+
+        /* Boolean 'present' flags */
+        { &hf_ppi_antenna_present_flags,
+          { "flags", "ppi_antenna.present.flags",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_FLAGS,
+            "Specifies if the flags bitfield is present", HFILL } },
+        { &hf_ppi_antenna_present_gaindb,
+          { "gaindb", "ppi_antenna.present.gaindb",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_GAINDB,
+            "Specifies if the antenna gain field  is present", HFILL } },
+        { &hf_ppi_antenna_present_horizbw,
+          { "horizbw", "ppi_antenna.present.horizbw",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_HORIZBW,
+            "Specifies if the horizontal beamwidth field is present", HFILL } },
+        { &hf_ppi_antenna_present_vertbw,
+          { "vertbw", "ppi_antenna.present.vertbw",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_VERTBW,
+            "Specifies if the vertical beamwidth field is present", HFILL } },
+        { &hf_ppi_antenna_present_pgain,
+          { "pgain", "ppi_antenna.present.pgain",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_PGAIN,
+            "Specifies if the precision gain field is present", HFILL } },
+        { &hf_ppi_antenna_present_beamid,
+          { "beamid", "ppi_antenna.present.beamid",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_BEAMID,
+            "Specifies if the BeamID field is present", HFILL } },
+        { &hf_ppi_antenna_present_serialnum,
+          { "serialnum", "ppi_antenna.present.serialnum",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_SERIALNUM,
+            "Specifies if the serial num is present", HFILL } },
+        { &hf_ppi_antenna_present_modelname,
+          { "modelname", "ppi_antenna.present.modelname",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_MODELSTR,
+            "Specifies if the model name is present", HFILL } },
+        { &hf_ppi_antenna_present_descstr,
+          { "Description", "ppi_antenna.present.descr",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_DESCSTR,
+            "Specifies if the description string is present", HFILL } },
+
+        { &hf_ppi_antenna_present_appspecific_num,
+          { "appid", "ppi_antenna.present.appid",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_APPID,
+            "Specifies if the application specific field id is present", HFILL } },
+
+        { &hf_ppi_antenna_present_appspecific_data,
+          { "appdata", "ppi_antenna.present.appdata",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_APPDATA,
+            "Specifies if the application specific data field  is present", HFILL } },
+
+        { &hf_ppi_antenna_present_ext,
+          { "ext", "ppi_antenna.present.ext",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNA_MASK_EXT,
+            "Specifies if there are any extensions to the header present ", HFILL } },
+
+        /*Here we switch to the antennflags bits*/
+        /* Boolean AntennaFlags' flags */
+        { &hf_ppi_antennaflags_mimo,
+          { "mimo", "ppi_antenna.antennaflags.mimo",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_MIMO,
+            "Antena is part of MIMO system", HFILL } },
+        { &hf_ppi_antennaflags_horizpol,
+          { "horizontally polarized", "ppi_antenna.antennaflags.horizpol",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_HPOL,
+            "Specifies if the antenna is horizontally polarized", HFILL } },
+
+        { &hf_ppi_antennaflags_vertpol,
+          { "vertically polarized", "ppi_antenna.antennaflags.vertpol",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_VPOL,
+            "Specifies if the antenna is vertically polarized", HFILL } },
+
+        { &hf_ppi_antennaflags_circpol_l,
+          { "circularly polarized left", "ppi_antenna.antennaflags.circpol_l",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_CPOL_L,
+            "Specifies if the antenna is circulary polarized, left handed", HFILL } },
+
+        { &hf_ppi_antennaflags_circpol_r,
+          { "circularly polarized right", "ppi_antenna.antennaflags.circpol_r",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_CPOL_R,
+            "Specifies if the antenna is circulary polarized, right handed", HFILL } },
+
+        { &hf_ppi_antennaflags_steer_elec,
+          { "electrically steerable", "ppi_antenna.antennaflags.steer_elec",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_STEER_ELEC,
+            "Specifies if the antenna is electrically steerable", HFILL } },
+
+        { &hf_ppi_antennaflags_steer_mech,
+          { "mechanically steerable", "ppi_antenna.antennaflags.steer_mech",
+            FT_BOOLEAN, 32, NULL, PPI_ANTENNAFLAGS_MASK_STEER_MECH,
+            "Specifies if the antenna is mechanically steerable", HFILL } },
+
+        /* Now we get to the actual data fields */
+        { &hf_ppi_antenna_gaindb,
+          { "Gain (dBi)", "ppi_antenna.gaindb",
+            FT_UINT8, BASE_DEC, NULL, 0x0,
+            "Gain of antenna (dBi)", HFILL } },
+        { &hf_ppi_antenna_horizbw,
+          { "HorizBw", "ppi_antenna.horizbw",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Horizontal beamwidth", HFILL } },
+        { &hf_ppi_antenna_vertbw,
+          { "VertBw", "ppi_antenna.vertbw",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Vertical beamwidth", HFILL } },
+        { &hf_ppi_antenna_pgain,
+          { "Precision Gain (dBi)", "ppi_antenna.pgain",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Precision Gain", HFILL } },
+        { &hf_ppi_antenna_beamid,
+          { "BeamID", "ppi_antenna.beamid",
+            FT_UINT16, BASE_HEX, NULL, 0x0,
+            "BeamID", HFILL } },
+
+        { &hf_ppi_antenna_serialnum,
+          { "SerialNumber", "ppi_antenna.serialnum",
+            FT_STRING,  BASE_NONE, NULL, 0x0,
+            "Serial number", HFILL } } ,
+        { &hf_ppi_antenna_modelname,
+          { "ModelName", "ppi_antenna.modelname",
+            FT_STRING,  BASE_NONE, NULL, 0x0,
+            "Model name", HFILL } } ,
+        { &hf_ppi_antenna_descstr,
+          { "Description", "ppi_antenna.descr",
+            FT_STRING,  BASE_NONE, NULL, 0x0,
+            "Description", HFILL } } ,
+        { &hf_ppi_antenna_appspecific_num,
+          { "Application Specific id", "ppi_antenna.appid",
+            FT_UINT32, BASE_HEX, NULL, 0x0,
+            "application specific identifier", HFILL } },
+        { &hf_ppi_antenna_appspecific_data,
+          { "Application specific data", "ppi_antenna.appdata",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            "application specific data", HFILL } },
+    };
+    static gint *ett[] = {
+        &ett_ppi_antenna,
+        &ett_ppi_antenna_present,
+        &ett_ppi_antennaflags
+    };
+
+    proto_ppi_antenna = proto_register_protocol("PPI antenna decoder", "PPI antenna Decoder", "ppi_antenna");
+    proto_register_field_array(proto_ppi_antenna, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+    register_dissector("ppi_antenna", dissect_ppi_antenna, proto_ppi_antenna);
+
+}
+void dissect_ppi_antenna(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+    /* The fixed values up front */
+    guint32 version;
+    guint length;
+    guint length_remaining;
+
+    proto_tree *ppi_antenna_tree = NULL;
+    proto_tree *present_tree = NULL;
+    proto_tree *antennaflags_tree = NULL;
+    proto_tree *pt, *my_pt;
+    proto_item *ti = NULL;
+
+
+    /* bits */
+    int bit;
+    guint32 present, next_present;
+    /* values actually read out, for displaying */
+    guint8 gaindb;
+    guint16 beamid;
+    guint32 t_hbw, t_vbw, t_pgain, t_appspecific_num; /* temporary conversions */
+    gdouble horizbw, vertbw, pgain;
+    guint32 flags;
+    char  *curr_str; /* used for modelname, serialnum, etc */
+
+    int offset = 0;
+
+    /* Clear out stuff in the info column */
+    if (check_col(pinfo->cinfo,COL_INFO)) {
+        col_clear(pinfo->cinfo,COL_INFO);
+    }
+    version = tvb_get_guint8(tvb, offset);
+    length = tvb_get_letohs(tvb, offset+2);
+    present = tvb_get_letohl(tvb, offset+4);
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_add_fstr(pinfo->cinfo, COL_INFO, "PPI Antenna info v%u, Length %u",
+                     version, length);
+
+    /* Dissect the packet */
+    if (tree) {
+        ti = proto_tree_add_protocol_format(tree, proto_ppi_antenna,
+                                            tvb, 0, length, "PPI Antenna Header v%u, Length %u", version, length);
+        ppi_antenna_tree= proto_item_add_subtree(ti, ett_ppi_antenna);
+        proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_version,
+                            tvb, offset, 1, version);
+        proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_pad,
+                            tvb, offset + 1, 1, FALSE);
+        ti = proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_length,
+                                 tvb, offset + 2, 2, length);
+    }
+    length_remaining = length;
+    /*
+     * FIXME: This only works if there is exactly 1 it_present
+     *        field in the header
+     */
+    if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
+        /*
+         * Radiotap header is shorter than the fixed-length portion
+         * plus one "present" bitset.
+         */
+        if (tree)
+            proto_item_append_text(ti, " (bogus - minimum length is 8)");
+        return;
+    }
+    /* Subtree for the "present flags" bitfield. */
+    if (tree) {
+        pt = proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_present, tvb, offset + 4, 4, present);
+        present_tree = proto_item_add_subtree(pt, ett_ppi_antenna_present);
+
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_flags, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_gaindb, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_horizbw, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_vertbw, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_pgain, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_beamid, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_serialnum, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_modelname, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_descstr, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_appspecific_num, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_appspecific_data, tvb, 4, 4, TRUE);
+
+        proto_tree_add_item(present_tree, hf_ppi_antenna_present_ext, tvb, 4, 4, TRUE);
+    }
+    offset += PPI_GEOBASE_MIN_HEADER_LEN;
+    length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;
+
+    /* Now all of the fixed length, fixed location stuff is over. Loop over the bits */
+    for (; present; present = next_present) {
+        /* clear the least significant bit that is set */
+        next_present = present & (present - 1);
+        /* extract the least significant bit that is set */
+        bit = BITNO_32(present ^ next_present);
+        switch (bit) {
+        case  PPI_ANTENNA_ANTFLAGS:
+            if (length_remaining < 4)
+                break;
+            flags = tvb_get_letohl(tvb, offset);
+            if (tree) {
+                my_pt = proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_flags, tvb, offset , 4, flags);
+                /*Add antenna_flags bitfields here */
+                antennaflags_tree= proto_item_add_subtree(my_pt, ett_ppi_antennaflags);
+
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_mimo, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_horizpol, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_vertpol, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_circpol_l, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_circpol_r, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_steer_elec, tvb, offset, 4, TRUE);
+                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_steer_mech, tvb, offset, 4, TRUE);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case PPI_ANTENNA_GAINDB:
+            if (length_remaining < 1)
+                break;
+            gaindb=  tvb_get_guint8(tvb, offset);
+            if (tree) {
+                proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_gaindb, tvb, offset, 1, gaindb);
+            }
+            offset+=1;
+            length_remaining-=1;
+            break;
+        case  PPI_ANTENNA_HORIZBW:
+            if (length_remaining < 4)
+                break;
+            t_hbw = tvb_get_letohl(tvb, offset);
+            horizbw =  fixed3_6_to_gdouble(t_hbw);
+            if (tree) {
+                proto_tree_add_float(ppi_antenna_tree, hf_ppi_antenna_horizbw, tvb, offset, 4, horizbw);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_ANTENNA_VERTBW:
+            if (length_remaining < 4)
+                break;
+            t_vbw = tvb_get_letohl(tvb, offset);
+            vertbw =  fixed3_6_to_gdouble(t_vbw);
+            if (tree) {
+                proto_tree_add_float(ppi_antenna_tree, hf_ppi_antenna_vertbw, tvb, offset, 4, vertbw);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_ANTENNA_PGAIN:
+            if (length_remaining < 4)
+                break;
+            t_pgain = tvb_get_letohl(tvb, offset);
+            pgain =  fixed3_6_to_gdouble(t_pgain);
+            if (tree) {
+                proto_tree_add_float(ppi_antenna_tree, hf_ppi_antenna_pgain, tvb, offset, 4, pgain);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_ANTENNA_BEAMID:
+            if (length_remaining < 2)
+                break;
+            beamid= tvb_get_letohs(tvb, offset); /* convert endianess */
+            if (tree) {
+                proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_beamid, tvb, offset, 2, beamid);
+            }
+            offset+=2;
+            length_remaining-=2;
+            break;
+        case  PPI_ANTENNA_SERIALNUM:
+            if (length_remaining < 32)
+                break;
+            if (tree) {
+                curr_str= (char *)  tvb_get_ptr(tvb, offset, 32);
+                proto_tree_add_string(ppi_antenna_tree, hf_ppi_antenna_serialnum, tvb, offset, 32, curr_str);;
+            }
+            offset+=32;
+            length_remaining-=32;
+            break;
+
+        case  PPI_ANTENNA_MODELSTR:
+            if (length_remaining < 32)
+                break;
+            if (tree) {
+                curr_str = (char *)  tvb_get_ptr(tvb, offset, 32);
+                proto_tree_add_string(ppi_antenna_tree, hf_ppi_antenna_modelname, tvb, offset, 32,  curr_str);
+            }
+            offset+=32;
+            length_remaining-=32;
+            break;
+        case  PPI_ANTENNA_DESCSTR:
+            if (length_remaining < 32)
+                break;
+            if (tree) {
+                curr_str= (char *)  tvb_get_ptr(tvb, offset, 32);
+                proto_tree_add_string(ppi_antenna_tree, hf_ppi_antenna_descstr, tvb, offset, 32, curr_str);
+            }
+            offset+=32;
+            length_remaining-=32;
+            break;
+        case  PPI_ANTENNA_APPID:
+            if (length_remaining < 4)
+                break;
+            t_appspecific_num  = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
+            if (tree) {
+                proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_appspecific_num, tvb, offset, 4, t_appspecific_num);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_ANTENNA_APPDATA:
+            if (length_remaining < 60)
+                break;
+            if (tree) {
+                proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_appspecific_data, tvb, offset, 60,  FALSE);
+            }
+            offset+=60;
+            length_remaining-=60;
+            break;
+        default:
+            /*
+             * This indicates a field whose size we do not
+             * know, so we cannot proceed.
+             */
+            proto_tree_add_text(ppi_antenna_tree, tvb, offset, 0,  "Error: PPI-ANTENNA: unknown bit (%d) set in present field.\n", bit);
+            next_present = 0;
+            continue;
+        }
+
+    };
+    return;
+}
+
+
diff --git a/epan/dissectors/packet-ppi-geolocation-common.c b/epan/dissectors/packet-ppi-geolocation-common.c
new file mode 100644 (file)
index 0000000..094c8fc
--- /dev/null
@@ -0,0 +1,74 @@
+/* packet-ppi-geolocation-common.c
+ * Routines for PPI-GEOLOCATION  dissection
+ * Copyright 2010, Harris Corp, jellch@harris.com
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "packet-ppi-geolocation-common.h"
+
+/*
+ * input: a unsigned 32-bit (native endian) value between 0 and 3600000000 (inclusive)
+ * output: a signed floating point value betwen -180.0000000 and + 180.0000000, inclusive)
+ */
+gdouble fixed3_7_to_gdouble(guint32 in) {
+    gint32 remapped_in = in - (180 * 10000000);
+    gdouble ret = (gdouble) ((gdouble) remapped_in / 10000000);
+    return ret;
+}
+/*
+ * input: a native 32 bit unsigned value between 0 and 999999999
+ * output: a positive floating point value between 000.0000000 and 999.9999999
+ */
+
+gdouble fixed3_6_to_gdouble(guint32 in) {
+    gdouble ret = (gdouble) in  / 1000000.0;
+    return ret;
+
+}
+/*
+ * input: a native 32 bit unsigned value between 0 and 3600000000
+ * output: a signed floating point value between -180000.0000 and +180000.0000
+ */
+gdouble fixed6_4_to_gdouble(guint32 in) {
+    gint32 remapped_in = in - (180000 * 10000);
+    gdouble ret = (gdouble) ((gdouble) remapped_in / 10000);
+    return ret;
+}
+
+gdouble ns_counter_to_gdouble(guint32 in) {
+    gdouble ret;
+    ret = (gdouble) in / 1000000000;
+    return ret;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/epan/dissectors/packet-ppi-geolocation-common.h b/epan/dissectors/packet-ppi-geolocation-common.h
new file mode 100644 (file)
index 0000000..d92a855
--- /dev/null
@@ -0,0 +1,92 @@
+/* packet-ppi-geolocation-common.h
+ * Routines for PPI-GEOLOCATION  dissection
+ * Copyright 2010, Harris Corp, jellch@harris.com
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PPI_GEOLOCATION_COMMON_H
+#define __PPI_GEOLOCATION_COMMON_H
+#include <glib.h>
+
+/*
+ * Declarations from shared PPI-GEOLOCATION functions.
+ *
+ */
+
+/*
+ * these constants are offsets into base_geotag header, which is bitwise-compatible
+ * with a radiotap header
+ */
+#define PPI_GEOBASE_MIN_HEADER_LEN  8   /* minimum header length */
+#define PPI_GEOBASE_VERSION_OFFSET  0   /* offset of version field */
+#define PPI_GEOBASE_LENGTH_OFFSET   2   /* offset of length field */
+#define PPI_GEOBASE_PRESENT_OFFSET  4   /* offset of "present" field */
+/*
+ * These BITNO macros were accquired from the radiotap parser. maybe we can share them
+ * eventually
+ */
+#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
+#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
+#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
+#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
+#define BITNO_2(x) (((x) & 2) ? 1 : 0)
+#define BIT(n)  (1 << n)
+
+
+
+/*
+ * Floating point numbers are stored on disk in a handful of fixed-point formats (fixedX_Y)
+ * designed to preserve the appropriate amount of precision vs range. These functions convert
+ * the fixedX_Y fixed point values into 'native' gdoubles for displaying.
+ * Documentation on these formats can be found in the PPI-GEOLOCATION specification
+ */
+gdouble fixed3_7_to_gdouble(guint32 in);
+gdouble fixed3_6_to_gdouble(guint32 in);
+gdouble fixed6_4_to_gdouble(guint32 in);
+/*
+ * Some values are encoded as 32-bit unsigned nano-second counters.
+ * Usually we want to display these values as doubles.
+ */
+gdouble ns_counter_to_gdouble(guint32 in);
+
+
+typedef enum {
+    PPI_GEOLOCATION_HARRIS   =  0x00485253 /* 00SRH */
+} ppi_geolocation_appstr_num;
+
+
+#endif
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
+
+
diff --git a/epan/dissectors/packet-ppi-gps.c b/epan/dissectors/packet-ppi-gps.c
new file mode 100644 (file)
index 0000000..d319303
--- /dev/null
@@ -0,0 +1,624 @@
+/* packet-ppi-gps.c
+ * Routines for PPI-GEOLOCATION-GPS  dissection
+ * Copyright 2010, Harris Corp, jellch@harris.com
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-radiotap.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/ptvcursor.h>
+#include <epan/prefs.h>
+#include <epan/reassemble.h>
+#include <epan/dissectors/packet-ppi-geolocation-common.h>
+enum ppi_geotagging_type {
+    PPI_GEOTAG_GPSFLAGS = 0,
+    PPI_GEOTAG_LAT = 1,
+    PPI_GEOTAG_LON = 2,
+    PPI_GEOTAG_ALT = 3,
+    PPI_GEOTAG_ALT_G = 4,
+    PPI_GEOTAG_GPSTIME = 5,
+    PPI_GEOTAG_FRACTIONALTIME = 6,
+    PPI_GEOTAG_EPH = 7,
+    PPI_GEOTAG_EPV = 8,
+    PPI_GEOTAG_EPT = 9,
+    PPI_GEOTAG_DESCRIPTIONSTR = 28,
+    PPI_GEOTAG_APPID = 29,
+    PPI_GEOTAG_APPDATA = 30,
+    PPI_GEOTAG_EXT = 31
+};
+#define PPI_GPS_MAXTAGLEN  148 /* This increases as fields above are added */
+
+
+/* protocol */
+static int proto_ppi_gps = -1;
+
+static int hf_ppi_gps_version = -1;
+static int hf_ppi_gps_pad = -1;
+static int hf_ppi_gps_length = -1;
+static int hf_ppi_gps_present = -1;
+static int hf_ppi_gps_gpsflags_flags = -1;
+static int hf_ppi_gps_lon = -1;
+static int hf_ppi_gps_lat = -1;
+static int hf_ppi_gps_alt = -1;
+static int hf_ppi_gps_alt_gnd = -1;
+static int hf_ppi_gps_gpstime = -1;
+static int hf_ppi_gps_fractime = -1;
+static int hf_ppi_gps_eph = -1;
+static int hf_ppi_gps_epv = -1;
+static int hf_ppi_gps_ept = -1;
+static int hf_ppi_gps_descr = -1;
+static int hf_ppi_gps_appspecific_num = -1; /* 4-byte tag no */
+static int hf_ppi_gps_appspecific_data = -1; /* 60 byte arbitrary data */
+/* "Present" flags, tese represent decoded-bits in the gui */
+static int hf_ppi_gps_present_gpsflags_flags = -1;
+static int hf_ppi_gps_present_lon = -1;
+static int hf_ppi_gps_present_lat = -1;
+static int hf_ppi_gps_present_alt = -1;
+static int hf_ppi_gps_present_alt_gnd = -1;
+static int hf_ppi_gps_present_gpstime = -1;
+static int hf_ppi_gps_present_fractime = -1;
+static int hf_ppi_gps_present_eph = -1;
+static int hf_ppi_gps_present_epv = -1;
+static int hf_ppi_gps_present_ept = -1;
+static int hf_ppi_gps_present_descr = -1;
+static int hf_ppi_gps_present_appspecific_num = -1;
+static int hf_ppi_gps_present_appspecific_data = -1;
+static int hf_ppi_gps_present_ext = -1;
+
+/* Devicetype flags. not to be confused with "present" flags. These are optional */
+static int hf_ppi_gps_gpsflags_flag0_nofix = -1;
+static int hf_ppi_gps_gpsflags_flag1_gpsfix = -1;
+static int hf_ppi_gps_gpsflags_flag2_diffgps = -1;
+static int hf_ppi_gps_gpsflags_flag3_PPS = -1;
+static int hf_ppi_gps_gpsflags_flag4_RTK = -1;
+static int hf_ppi_gps_gpsflags_flag5_floatRTK = -1;
+static int hf_ppi_gps_gpsflags_flag6_dead_reck = -1;
+static int hf_ppi_gps_gpsflags_flag7_manual = -1;
+static int hf_ppi_gps_gpsflags_flag8_sim = -1;
+
+/* These represent arrow-dropdownthings in the gui */
+static gint ett_ppi_gps = -1;
+static gint ett_ppi_gps_present = -1;
+static gint ett_ppi_gps_gpsflags_flags= -1;
+
+static void
+dissect_ppi_gps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+proto_register_ppi_gps(void) {
+    /* The following array initializes those header fields declared above to the values displayed */
+    static hf_register_info hf[] = {
+        { &hf_ppi_gps_version,
+            { "Header revision", "ppi_gps.version",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Version of ppi_gps header format", HFILL } },
+        { &hf_ppi_gps_pad,
+          { "Header pad", "ppi_gps.pad",
+            FT_UINT8, BASE_DEC, NULL, 0x0,
+            "Padding", HFILL } },
+        { &hf_ppi_gps_length,
+          { "Header length", "ppi_gps.length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of header including version, pad, length and data fields", HFILL } },
+        { &hf_ppi_gps_present, /* these flag fields are composed of a uint32 on the display */
+          { "Present", "ppi_gps.present",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating which fields are present", HFILL } },
+
+#define PPI_GPS_MASK_GPSFLAGS          0x00000001
+#define PPI_GPS_MASK_LAT                       0x00000002
+#define PPI_GPS_MASK_LON                       0x00000004
+#define PPI_GPS_MASK_ALT           0x00000008
+#define PPI_GPS_MASK_ALT_G         0x00000010
+
+#define PPI_GPS_MASK_GPSTIME           0x00000020
+#define PPI_GPS_MASK_FRACTIME          0x00000040
+#define PPI_GPS_MASK_EPH                       0x00000080
+#define PPI_GPS_MASK_EPV                       0x00000100
+#define PPI_GPS_MASK_EPT                       0x00000200
+
+#define PPI_GPS_MASK_DESCRSTR          0x10000000
+#define PPI_GPS_MASK_APPID                     0x20000000
+#define PPI_GPS_MASK_APPDATA           0x40000000
+#define PPI_GPS_MASK_EXT            0x80000000
+
+        /* Boolean 'present' flags */
+        { &hf_ppi_gps_present_gpsflags_flags, /* followed by a lot of booleans */
+          { "GPSFlags", "ppi_gps.present.gpsflagss",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_GPSFLAGS,
+            "32-bit bitmask indicating type of GPS fix (GPS/INS/software/etc)", HFILL } },
+        { &hf_ppi_gps_present_lat,
+          { "Lat", "ppi_gps.present.lat",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_LAT,
+            "Specifies if the latitude field is present", HFILL } },
+
+        { &hf_ppi_gps_present_lon,
+          { "Lon", "ppi_gps.present.lon",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_LON,
+            "Specifies if the longitude field is present", HFILL } },
+
+        { &hf_ppi_gps_present_alt,
+          { "Alt", "ppi_gps.present.alt",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_ALT,
+            "Specifies if the altitude field is present", HFILL } },
+
+        { &hf_ppi_gps_present_alt_gnd,
+          { "Alt-gnd", "ppi_gps.present.alt_gnd",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_ALT_G,
+            "Specifies if the altitude-g field is present", HFILL } },
+
+        { &hf_ppi_gps_present_gpstime,
+          { "GPStime", "ppi_gps.present.gpstime",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_GPSTIME,
+            "Specifies if the GPS time field is present", HFILL } },
+
+
+        { &hf_ppi_gps_present_fractime,
+          { "fractime", "ppi_gps.present.fractime",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_FRACTIME,
+            "Specifies if the fractional time field is present", HFILL } },
+
+
+        { &hf_ppi_gps_present_eph,
+          { "error_h", "ppi_gps.present.eph",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_EPH,
+            "Specifies if the horizontal error field is present (eph)", HFILL } },
+
+        { &hf_ppi_gps_present_epv,
+          { "error_v", "ppi_gps.present.epv",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_EPV,
+            "Specifies if the vertical error field present (epv)", HFILL } },
+
+
+        { &hf_ppi_gps_present_ept,
+          { "error_t", "ppi_gps.present.ept",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_EPT,
+            "Specifies if the estimed time error field is present (ept)", HFILL } },
+
+        { &hf_ppi_gps_present_descr,
+          { "Description", "ppi_gps.present.descr",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_DESCRSTR,
+            "Specifies if the (ASCII) description is present", HFILL } },
+
+        { &hf_ppi_gps_present_appspecific_num,
+          { "AppId", "ppi_gps.present.appid",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_APPID,
+            "Specifies if the application specific field id is present", HFILL } },
+
+        { &hf_ppi_gps_present_appspecific_data,
+          { "AppData", "ppi_gps.present.appdata",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_APPDATA,
+            "Specifies if the application specific data field  is present", HFILL } },
+
+        { &hf_ppi_gps_present_ext,
+          { "Ext", "ppi_gps.present.ext",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_MASK_EXT,
+            "Specifies if there are any extensions to the header present", HFILL } },
+
+        /* ---Now we get to the actual data fields--- */
+
+        { &hf_ppi_gps_gpsflags_flags,
+          { "GPSFlags", "ppi_gps.gpsflags",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating GPS/INS/manual fix", HFILL } },
+        { &hf_ppi_gps_lat,
+          { "Latitude", "ppi_gps.lat",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Latitude packet was received at", HFILL } },
+        { &hf_ppi_gps_lon,
+          { "Longitude", "ppi_gps.lon",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Longitude packet was received at", HFILL } },
+        { &hf_ppi_gps_alt,
+          { "Altitude", "ppi_gps.alt",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Altitude packet was received at", HFILL } },
+        { &hf_ppi_gps_alt_gnd,
+          { "Altitude_gnd", "ppi_gps.alt_gnd",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Altitude packet was received at (relative to ground)", HFILL } },
+        { &hf_ppi_gps_gpstime,
+          { "GPSTimestamp", "ppi_gps.gpstime",
+            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
+            "GPSTimestamp packet was received at", HFILL } },
+        { &hf_ppi_gps_fractime,
+          { "fractional Timestamp", "ppi_gps.fractime",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "fractional GPSTimestamp packet was received at", HFILL } },
+        { &hf_ppi_gps_eph,
+          { "Horizontal Error (m)", "ppi_gps.eph",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Horizontal margin of error (meters)", HFILL } },
+        { &hf_ppi_gps_epv,
+          { "Vertical Error (m)", "ppi_gps.epv",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Vertical margin of error (meters) ", HFILL } },
+        { &hf_ppi_gps_ept,
+          { "Time Error (s)", "ppi_gps.ept",
+            FT_DOUBLE, BASE_NONE, NULL, 0x0,
+            "Time margin of error (secs)", HFILL } },
+        { &hf_ppi_gps_descr,
+          { "Description", "ppi_gps.descr",
+            FT_STRING, BASE_NONE, NULL, 0x0,
+            "Description", HFILL } },
+        { &hf_ppi_gps_appspecific_num,
+          { "Application Specific id", "ppi_gps.appid",
+            FT_UINT32, BASE_HEX, NULL, 0x0,
+            "application specific identifier", HFILL } },
+        { &hf_ppi_gps_appspecific_data,
+          { "Application specific data", "ppi_gps.appdata",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            "application specific data", HFILL } },
+
+        /* --- moving on to the 'FixType' flags --- */
+#define PPI_GPS_GPSFLAGS_FLAG0_NOFIX           0x00000001
+#define PPI_GPS_GPSFLAGS_FLAG1_GPS             0x00000002
+#define PPI_GPS_GPSFLAGS_FLAG2_DIFFGPS 0x00000004
+#define PPI_GPS_GPSFLAGS_FLAG3_PPS             0x00000008
+#define PPI_GPS_GPSFLAGS_FLAG4_RTK             0x00000010
+#define PPI_GPS_GPSFLAGS_FLAG5_FLOATRTK        0x00000020
+#define PPI_GPS_GPSFLAGS_FLAG6_DEAD_RECK       0x00000040
+#define PPI_GPS_GPSFLAGS_FLAG7_MANUAL  0x00000080
+#define PPI_GPS_GPSFLAGS_FLAG8_SIM             0x00000100
+        { &hf_ppi_gps_gpsflags_flag0_nofix, /* no fix available */
+          { "No fix available", "ppi_gps.gpsflagss.nofix",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG0_NOFIX,
+            "No GPS fix available", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag1_gpsfix, /* GPSfix available */
+          { "GPS provided fix", "ppi_gps.gpsflagss.gps",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG1_GPS,
+            "GPS provided fix", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag2_diffgps, /* Differential GPS fix  available */
+          { "Differential GPS provided fix", "ppi_gps.gpsflagss.diffgps",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG2_DIFFGPS,
+            "DGPS provided fix", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag3_PPS, /* PPS fix  */
+          { "PPS fix", "ppi_gps.gpsflagss.pps",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG3_PPS,
+            " PPS fix ", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag4_RTK, /* RTK fix*/
+          { "RTK fix", "ppi_gps.gpsflagss.rtk",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG4_RTK,
+            "RTK  fix ", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag5_floatRTK, /*float RTK */
+          { "floatRTK fix", "ppi_gps.gpsflagss.frtk",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG5_FLOATRTK,
+            " floatRTK fix ", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag6_dead_reck, /*dead reckoning */
+          { "dead reckoning fix", "ppi_gps.gpsflagss.dead_reck",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG6_DEAD_RECK,
+            "dead reckoning fix ", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag7_manual, /* manual */
+          { "manual fix", "ppi_gps.gpsflagss.manual",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG7_MANUAL,
+            "manual  fix available", HFILL } },
+        { &hf_ppi_gps_gpsflags_flag8_sim, /* simulation */
+          { "simulated fix", "ppi_gps.gpsflagss.simulation",
+            FT_BOOLEAN, 32, NULL, PPI_GPS_GPSFLAGS_FLAG8_SIM,
+            "simulated fix", HFILL } },
+
+    };
+    static gint *ett[] = {
+        &ett_ppi_gps,
+        &ett_ppi_gps_present,
+        &ett_ppi_gps_gpsflags_flags
+    };
+
+    proto_ppi_gps = proto_register_protocol("PPI Geotagging GPS tag decoder", "PPI GPS Decoder", "ppi_gps");
+    proto_register_field_array(proto_ppi_gps, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+    register_dissector("ppi_gps", dissect_ppi_gps, proto_ppi_gps);
+
+}
+void dissect_ppi_gps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+    /* These are locals used for processing the current tvb */
+    guint length;
+    guint length_remaining;
+    int offset = 0;
+
+    proto_tree *ppi_gps_tree = NULL;
+    proto_tree *pt, *present_tree = NULL;
+    proto_tree *my_pt, *gpsflags_flags_tree = NULL; /* used for DeviceType bitmask stuff */
+
+    proto_item *ti = NULL;
+
+
+    /* bits */
+    int bit;
+    guint32 present, next_present;
+    /* values actually read out, for displaying */
+    guint32 version, gpsflags_flags;
+    gdouble lat, lon, alt, alt_gnd;
+    nstime_t gps_timestamp;
+    int gps_time_size, already_processed_fractime; /* we use this internally to track if this is a 4 or 8 byte wide timestamp */
+    gdouble eph, epv, ept;
+
+    /* these are temporary intermediate values, used in the individual cases below */
+    guint32 t_lat, t_lon, t_alt, t_alt_gnd;
+    guint32 t_herr, t_verr, t_terr;
+    guint32 t_appspecific_num;
+    /* initialize the timestamp value(s) */
+    gps_timestamp.secs = gps_timestamp.nsecs = gps_time_size = already_processed_fractime = 0;
+
+    /* Clear out stuff in the info column */
+    if (check_col(pinfo->cinfo,COL_INFO))
+        col_clear(pinfo->cinfo,COL_INFO);
+    /* pull out the first three fields of the BASE-GEOTAG-HEADER */
+    version = tvb_get_guint8(tvb, offset);
+    length = tvb_get_letohs(tvb, offset+2);
+    present = tvb_get_letohl(tvb, offset+4);
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_GPS Capture v%u, Length %u", version, length);
+
+    /* Dissect the packet */
+    if (tree) {
+        ti = proto_tree_add_protocol_format(tree, proto_ppi_gps,
+                                            tvb, 0, length, "PPI GPS Header v%u, Length %u", version, length);
+        ppi_gps_tree= proto_item_add_subtree(ti, ett_ppi_gps);
+        proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_version, tvb, offset, 1, version);
+        proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_pad, tvb, offset + 1, 1, FALSE);
+        ti = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_length, tvb, offset + 2, 2, length);
+    }
+    /* basic length sanity checking */
+    if (length > PPI_GPS_MAXTAGLEN ) {
+        if (tree)
+            proto_item_append_text(ti, "Invalid PPI-GPS length  (got %d, %d max\n)", length, PPI_GPS_MAXTAGLEN);
+        return;
+    }
+    /* no minimum length check, technically zero is valid */
+
+    /* initialize the length of the actual tag contents */
+    length_remaining = length;
+    if (version != 1) {
+        if (tree)
+            proto_item_append_text(ti, "invalid version (got %d, expected 1)", version);
+        return;
+    }
+
+    /*
+     * This only works if there is exactly 1 present
+     * field in the header. This is not a problem as there are currently no extended bitmasks defined.
+     */
+    if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
+        /*
+         * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion
+         * plus one "present" bitset.
+         */
+        if (tree)
+            proto_item_append_text(ti, " (bogus - minimum length is 8)");
+        return;
+    }
+    /* Subtree for the "present flags" bitfield. */
+    if (tree) {
+        pt = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_present, tvb, offset + 4, 4, present);
+        present_tree = proto_item_add_subtree(pt, ett_ppi_gps_present);
+
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_gpsflags_flags, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_lat, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_lon, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_alt, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_alt_gnd, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_gpstime, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_fractime, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_eph, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_epv, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_ept, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_descr, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_appspecific_num, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_appspecific_data, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_gps_present_ext, tvb, 4, 4, TRUE);
+    }
+    offset += PPI_GEOBASE_MIN_HEADER_LEN;
+    length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;
+
+    /* The fixed BASE-GEOTAG-HEADER has been handled at this point. move on to the individual fields */
+    for (; present; present = next_present) {
+        /* clear the least significant bit that is set */
+        next_present = present & (present - 1);
+        /* extract the least significant bit that is set */
+        bit = BITNO_32(present ^ next_present);
+        switch (bit) {
+        case PPI_GEOTAG_GPSFLAGS:
+            if (length_remaining < 4)
+                break;
+            gpsflags_flags =   tvb_get_letohl(tvb, offset); /* retrieve 32-bit gpsflags bitmask (-not- present bitmask) */
+            if (tree) {
+                /* first we add the hex flags line */
+                my_pt = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_gpsflags_flags, tvb, offset , 4, gpsflags_flags);
+                /* then we add a subtree */
+                gpsflags_flags_tree = proto_item_add_subtree(my_pt, ett_ppi_gps_gpsflags_flags);
+                /* to pin the individual bits on */
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag0_nofix, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag1_gpsfix, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag2_diffgps, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag3_PPS, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag4_RTK, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag5_floatRTK, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag6_dead_reck, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag7_manual, tvb, offset, 4, TRUE);
+                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag8_sim, tvb, offset, 4, TRUE);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_LAT:
+            if (length_remaining < 4)
+                break;
+            t_lat = tvb_get_letohl(tvb, offset);
+            lat =  fixed3_7_to_gdouble(t_lat);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lat, tvb, offset, 4, lat);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_LON:
+            if (length_remaining < 4)
+                break;
+            t_lon = tvb_get_letohl(tvb, offset);
+            lon =  fixed3_7_to_gdouble(t_lon);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lon, tvb, offset, 4, lon);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_ALT:
+            if (length_remaining < 4)
+                break;
+            t_alt = tvb_get_letohl(tvb, offset);
+            alt = fixed6_4_to_gdouble(t_alt);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt, tvb, offset, 4, alt);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_ALT_G:
+            if (length_remaining < 4)
+                break;
+            t_alt_gnd = tvb_get_letohl(tvb, offset);
+            alt_gnd = fixed6_4_to_gdouble(t_alt_gnd);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt_gnd, tvb, offset, 4, alt_gnd);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_GPSTIME:
+            if (length_remaining < 4)
+                break;
+            gps_timestamp.secs =    tvb_get_letohl(tvb, offset);
+            gps_timestamp.nsecs = 0;
+            gps_time_size = 4;
+            /* This is somewhat tricky, inside the GPSTIME case we test if the optional fractional time */
+            /* is present. If so, we pull it out, and combine it with GPSTime. */
+            /* If we do this, we set already_processed_fractime to avoid hitting it below */
+            if (length_remaining < 4 && (present & PPI_GPS_MASK_FRACTIME))
+                break;
+            else if (present & PPI_GPS_MASK_FRACTIME) {
+                gps_timestamp.nsecs =  tvb_get_letohl(tvb, offset + 4); /* manually offset seconds */
+                already_processed_fractime = 1;
+                gps_time_size = 8;
+            }
+            if (tree) {
+                proto_tree_add_time(ppi_gps_tree, hf_ppi_gps_gpstime, tvb, offset, gps_time_size, &gps_timestamp);
+            }
+            offset += gps_time_size;
+            length_remaining -= gps_time_size;
+            break;
+        case  PPI_GEOTAG_FRACTIONALTIME:
+            if (length_remaining < 4)
+                break;
+            if (already_processed_fractime)
+                break;
+            break;
+        case  PPI_GEOTAG_EPH:
+            if (length_remaining < 4)
+                break;
+            t_herr = tvb_get_letohl(tvb, offset);
+            eph  =  fixed3_6_to_gdouble(t_herr);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_eph, tvb, offset, 4, eph);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_EPV:
+            if (length_remaining < 4)
+                break;
+            t_verr = tvb_get_letohl(tvb, offset);
+            epv  =  fixed3_6_to_gdouble(t_verr);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_epv, tvb, offset, 4, epv);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_EPT:
+            if (length_remaining < 4)
+                break;
+            t_terr = tvb_get_letohl(tvb, offset);
+            ept  =  ns_counter_to_gdouble(t_terr);
+            if (tree)
+                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_ept, tvb, offset, 4, ept);
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_DESCRIPTIONSTR:
+            if (length_remaining < 32)
+                break;
+            if (tree)
+                proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_descr, tvb, offset, 32,  FALSE);
+            offset+=32;
+            length_remaining-=32;
+            break;
+        case  PPI_GEOTAG_APPID:
+            if (length_remaining < 4)
+                break;
+            t_appspecific_num  = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
+            if (tree) {
+                proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_appspecific_num, tvb, offset, 4, t_appspecific_num);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_GEOTAG_APPDATA:
+            if (length_remaining < 60)
+                break;
+            if (tree) {
+                proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_appspecific_data, tvb, offset, 60,  FALSE);
+            }
+            offset+=60;
+            length_remaining-=60;
+            break;
+
+            /*
+             * This indicates a field whose size we do not know, so we cannot proceed.
+             */
+        default:
+            next_present = 0; /* this will terminate the loop */
+            proto_tree_add_text(ppi_gps_tree, tvb, offset, 0,  "Error: PPI-GEOLOCATION-GPS: unknown bit (%d) set in present field.\n", bit);
+            continue;
+        } /* switch (bit) */
+
+    } /* (for present..)*/
+
+    /* If there was any post processing of the elements, it could happen here. */
+    return;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
+
+
+
diff --git a/epan/dissectors/packet-ppi-vector.c b/epan/dissectors/packet-ppi-vector.c
new file mode 100644 (file)
index 0000000..d352052
--- /dev/null
@@ -0,0 +1,929 @@
+/* packet-ppi-vector.c
+ * Routines for PPI-GEOLOCATION-VECTOR  dissection
+ * Copyright 2010, Harris Corp, jellch@harris.com
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-radiotap.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include <epan/ptvcursor.h>
+#include <epan/prefs.h>
+#include <epan/reassemble.h>
+#include "packet-ppi-geolocation-common.h"
+
+enum ppi_vector_type {
+    PPI_VECTOR_VFLAGS          = 0,
+    PPI_VECTOR_VCHARS          = 1,
+    PPI_VECTOR_ROTX        = 2,
+    PPI_VECTOR_ROTY        = 3,
+    PPI_VECTOR_ROTZ        = 4,
+    PPI_VECTOR_OFF_R           = 5,
+    PPI_VECTOR_OFF_F           = 6,
+    PPI_VECTOR_OFF_U       = 7,
+    PPI_VECTOR_VEL_R           = 8,
+    PPI_VECTOR_VEL_F           = 9,
+    PPI_VECTOR_VEL_U       = 10,
+    PPI_VECTOR_VEL_T       = 11,
+    PPI_VECTOR_ACC_R           = 12,
+    PPI_VECTOR_ACC_F           = 13,
+    PPI_VECTOR_ACC_U       = 14,
+    PPI_VECTOR_ACC_T       = 15,
+    PPI_VECTOR_ERR_ROT         = 16,
+    PPI_VECTOR_ERR_OFF         = 17,
+    PPI_VECTOR_ERR_VEL         = 18,
+    PPI_VECTOR_ERR_ACC         = 19,
+
+    PPI_VECTOR_DESCSTR      = 28,
+    PPI_VECTOR_APPID        = 29,
+    PPI_VECTOR_APPDATA      = 30,
+    PPI_VECTOR_EXT          = 31
+};
+
+
+/* protocol */
+static int proto_ppi_vector = -1;
+
+/* "top" level fields */
+static int hf_ppi_vector_version = -1;
+static int hf_ppi_vector_pad = -1;
+static int hf_ppi_vector_length = -1;
+static int hf_ppi_vector_present = -1;
+static int hf_ppi_vector_vflags = -1;
+static int hf_ppi_vector_vchars = -1;
+static int hf_ppi_vector_rot_x = -1;
+static int hf_ppi_vector_rot_y = -1;
+static int hf_ppi_vector_rot_z = -1;
+static int hf_ppi_vector_off_r = -1;
+static int hf_ppi_vector_off_f = -1;
+static int hf_ppi_vector_off_u = -1;
+static int hf_ppi_vector_vel_r = -1;
+static int hf_ppi_vector_vel_f = -1;
+static int hf_ppi_vector_vel_u = -1;
+static int hf_ppi_vector_vel_t = -1;
+static int hf_ppi_vector_acc_r = -1;
+static int hf_ppi_vector_acc_f = -1;
+static int hf_ppi_vector_acc_u = -1;
+static int hf_ppi_vector_acc_t = -1;
+
+static int hf_ppi_vector_err_rot= -1;
+static int hf_ppi_vector_err_off= -1;
+static int hf_ppi_vector_err_vel= -1;
+static int hf_ppi_vector_err_acc= -1;
+static int hf_ppi_vector_descstr= -1;
+static int hf_ppi_vector_appspecific_num = -1;
+static int hf_ppi_vector_appspecific_data = -1;
+
+/* "Present" flags */
+static int hf_ppi_vector_present_vflags = -1;
+static int hf_ppi_vector_present_vchars = -1;
+static int hf_ppi_vector_present_val_x = -1;
+static int hf_ppi_vector_present_val_y = -1;
+static int hf_ppi_vector_present_val_z = -1;
+static int hf_ppi_vector_present_off_r = -1;
+static int hf_ppi_vector_present_off_f = -1;
+static int hf_ppi_vector_present_off_u = -1;
+static int hf_ppi_vector_present_vel_r = -1;
+static int hf_ppi_vector_present_vel_f = -1;
+static int hf_ppi_vector_present_vel_u = -1;
+static int hf_ppi_vector_present_vel_t = -1;
+static int hf_ppi_vector_present_acc_r = -1;
+static int hf_ppi_vector_present_acc_f = -1;
+static int hf_ppi_vector_present_acc_u = -1;
+static int hf_ppi_vector_present_acc_t = -1;
+static int hf_ppi_vector_present_err_rot = -1;
+static int hf_ppi_vector_present_err_off = -1;
+static int hf_ppi_vector_present_err_vel = -1;
+static int hf_ppi_vector_present_err_acc = -1;
+static int hf_ppi_vector_present_descstr= -1;
+static int hf_ppi_vector_presenappsecific_num = -1;
+static int hf_ppi_vector_present_appspecific_data = -1;
+static int hf_ppi_vector_present_ext = -1;
+
+/* VectorFlags bits */
+/*  There are currently only three vector flags.
+*  These control the units/interpreration of a vector
+*/
+static int hf_ppi_vector_vflags_defines_forward        = -1;
+static int hf_ppi_vector_vflags_rots_absolute = -1; /* different ways to display the same bit, hi or low */
+static int hf_ppi_vector_vflags_offsets_from_gps = -1; /* these are different ways to display the same bit, hi or low */
+
+/*  There are currently eight vector characteristics.
+*  These are purely descriptive (no mathematical importance)
+*/
+static int hf_ppi_vector_vchars_antenna         = -1;
+static int hf_ppi_vector_vchars_dir_of_travel = -1;
+static int hf_ppi_vector_vchars_front_of_veh = -1;
+
+static int hf_ppi_vector_vchars_gps_derived = -1;
+static int hf_ppi_vector_vchars_ins_derived = -1;
+static int hf_ppi_vector_vchars_compass_derived = -1;
+static int hf_ppi_vector_vchars_accelerometer_derived = -1;
+static int hf_ppi_vector_vchars_human_derived = -1;
+
+/*These represent arrow-dropdownthings in the gui */
+static gint ett_ppi_vector = -1;
+static gint ett_ppi_vector_present = -1;
+static gint ett_ppi_vectorflags= -1;
+static gint ett_ppi_vectorchars= -1;
+
+static void dissect_ppi_vector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void proto_register_ppi_vector(void) {
+    /* The following array initializes those header fields declared above to the values displayed */
+    static hf_register_info hf[] = {
+        { &hf_ppi_vector_version,
+            { "Header revision", "ppi_vector.version",
+                FT_UINT8, BASE_DEC, NULL, 0x0,
+                "Version of ppi_vector header format", HFILL } },
+        { &hf_ppi_vector_pad,
+          { "Header pad", "ppi_vector.pad",
+            FT_UINT8, BASE_DEC, NULL, 0x0,
+            "Padding", HFILL } },
+        { &hf_ppi_vector_length,
+          { "Header length", "ppi_vector.length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of header including version, pad, length and data fields", HFILL } },
+        { &hf_ppi_vector_present,
+          { "Present", "ppi_vector.present",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating which fields are present", HFILL } },
+
+#define PPI_VECTOR_MASK_VFLAGS         0x00000001
+#define PPI_VECTOR_MASK_VCHARS         0x00000002
+#define PPI_VECTOR_MASK_ROTX           0x00000004
+#define PPI_VECTOR_MASK_ROTY           0x00000008
+#define PPI_VECTOR_MASK_ROTZ       0x00000010
+#define PPI_VECTOR_MASK_OFF_R          0x00000020
+#define PPI_VECTOR_MASK_OFF_F          0x00000040
+#define PPI_VECTOR_MASK_OFF_U              0x00000080
+#define PPI_VECTOR_MASK_VEL_R          0x00000100
+#define PPI_VECTOR_MASK_VEL_F          0x00000200
+#define PPI_VECTOR_MASK_VEL_U              0x00000400
+#define PPI_VECTOR_MASK_VEL_T              0x00000800
+#define PPI_VECTOR_MASK_ACC_R          0x00001000
+#define PPI_VECTOR_MASK_ACC_F          0x00002000
+#define PPI_VECTOR_MASK_ACC_U              0x00004000
+#define PPI_VECTOR_MASK_ACC_T              0x00008000
+
+#define PPI_VECTOR_MASK_ERR_ROT                0x00010000
+#define PPI_VECTOR_MASK_ERR_OFF                0x00020000
+#define PPI_VECTOR_MASK_ERR_VEL                0x00040000
+#define PPI_VECTOR_MASK_ERR_ACC                0x00080000
+
+#define PPI_VECTOR_MASK_DESCSTR    0x10000000  /* 28 */
+#define PPI_VECTOR_MASK_APPID      0x20000000  /* 29 */
+#define PPI_VECTOR_MASK_APPDATA    0x40000000  /* 30 */
+#define PPI_VECTOR_MASK_EXT         0x80000000  /* 31 */
+
+        /* Boolean 'present' flags */
+        { &hf_ppi_vector_present_vflags,
+          { "Vector flags", "ppi_vector.present.flags",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VFLAGS,
+            "Specifies if the Vector flags bitfield is present", HFILL } },
+
+        { &hf_ppi_vector_present_vchars,
+          { "Vector chararacteristics", "ppi_vector.present.chars",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VCHARS,
+            "Specifies if the Vector chars  bitfield is present", HFILL } },
+
+        { &hf_ppi_vector_present_val_x,
+          { "Pitch", "ppi_vector.present.pitch",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTX,
+            "Specifies if the rotate-x field (pitch) is present", HFILL } },
+
+        { &hf_ppi_vector_present_val_y,
+          { "Roll", "ppi_vector.present.roll",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTY,
+            "Specifies if the rotate-y field (roll) is present", HFILL } },
+
+        { &hf_ppi_vector_present_val_z,
+          { "Heading", "ppi_vector.present.heading",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ROTZ,
+            "Specifies if the rotate-z field (heading) is present", HFILL } },
+
+
+        { &hf_ppi_vector_present_off_r,
+          { "Offset_R", "ppi_vector.present.off_r",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_R,
+            "Specifies if the offset-right field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_off_f,
+          { "Offset_F", "ppi_vector.present.off_f",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_F,
+            "Specifies if the offset-forward  field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_off_u,
+          { "Offset_U", "ppi_vector.present.off_u",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_U,
+            "Specifies if the offset-up  field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_vel_r,
+          { "Velocity_R", "ppi_vector.present.vel_r",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_R,
+            "Specifies if the velocity-right field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_vel_f,
+          { "Velocity_F", "ppi_vector.present.vel_f",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_F,
+            "Specifies if the velocity-forward  field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_vel_u,
+          { "Velocity_U", "ppi_vector.present.vel_u",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_U,
+            "Specifies if the velocity-up  field  is present", HFILL } },
+        { &hf_ppi_vector_present_vel_t,
+          { "Velocity_T", "ppi_vector.present.vel_t",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_VEL_T,
+            "Specifies if the total velocity field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_acc_r,
+          { "Acceleration_R", "ppi_vector.present.acc_r",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_R,
+            "Specifies if the accel-right field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_acc_f,
+          { "Acceleration_F", "ppi_vector.present.acc_f",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_F,
+            "Specifies if the accel-forward  field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_acc_u,
+          { "Acceleration_U", "ppi_vector.present.acc_u",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_U,
+            "Specifies if the accel-up  field  is present", HFILL } },
+        { &hf_ppi_vector_present_acc_t,
+          { "Acceleration_T", "ppi_vector.present.acc_t",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ACC_T,
+            "Specifies if the total acceleration  field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_err_rot,
+          { "err_rot", "ppi_vector.present.err_rot",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_ROT,
+            "Specifies if the rotation error field is present", HFILL } },
+
+        { &hf_ppi_vector_present_err_off,
+          { "err_off", "ppi_vector.present.err_off",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_OFF,
+            "Specifies if the offset error field is present", HFILL } },
+
+        { &hf_ppi_vector_present_err_vel,
+          { "err_vel", "ppi_vector.present.err_vel",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_VEL,
+            "Specifies if the velocity  error field is present", HFILL } },
+
+        { &hf_ppi_vector_present_err_acc,
+          { "err_acc", "ppi_vector.present.err_acc",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_ERR_ACC,
+            "Specifies if the acceleration error field is present", HFILL } },
+
+        { &hf_ppi_vector_present_descstr,
+          { "descstr", "ppi_vector.present.descstr",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_DESCSTR,
+            "Specifies if the acceleration error field is present", HFILL } },
+
+        { &hf_ppi_vector_presenappsecific_num,
+          { "appid", "ppi_vector.present.appid",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_APPID,
+            "Specifies if the application specific field id is present", HFILL } },
+
+        { &hf_ppi_vector_present_appspecific_data,
+          { "appdata", "ppi_vector.present.appdata",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_APPDATA,
+            "Specifies if the application specific data field  is present", HFILL } },
+
+        { &hf_ppi_vector_present_ext,
+          { "Ext", "ppi_vector.present.ext",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_EXT,
+            "Specifies if there are any extensions to the header present", HFILL } },
+
+        /* Now we get to the actual data fields */
+        /* This setups the "Vector fflags" hex dropydown thing */
+        { &hf_ppi_vector_vflags,
+          { "Vector flags", "ppi_vector.vector_flags",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating coordinate sys, among others, etc", HFILL } },
+        { &hf_ppi_vector_vchars,
+          { "Vector chars", "ppi_vector.vector_chars",
+            FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating if vector tracks antenna, vehicle, motion, etc", HFILL } },
+        { &hf_ppi_vector_rot_x,
+          { "Pitch", "ppi_vector.pitch",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Pitch (Rotation x) packet was receivd at", HFILL } },
+        { &hf_ppi_vector_rot_y,
+          { "Roll", "ppi_vector.roll",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Roll (Rotation y) packet was receivd at", HFILL } },
+        { &hf_ppi_vector_rot_z,
+          { "Heading", "ppi_vector.heading",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Heading (Rotation z) packet was receivd at", HFILL } },
+        { &hf_ppi_vector_off_r,
+          { "Off-r", "ppi_vector.off_r",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Offset right", HFILL } },
+        { &hf_ppi_vector_off_f,
+          { "Off-f", "ppi_vector.off_f",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Offation forward", HFILL } },
+        { &hf_ppi_vector_off_u,
+          { "Off-u", "ppi_vector.off_u",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Offset up", HFILL } },
+        { &hf_ppi_vector_vel_r,
+          { "Vel-r", "ppi_vector.vel_r",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Velocity-right", HFILL } },
+        { &hf_ppi_vector_vel_f,
+          { "Vel-f", "ppi_vector.vel_f",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Velocity-forward", HFILL } },
+        { &hf_ppi_vector_vel_u,
+          { "Vel-u", "ppi_vector.vel_u",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Velocity-up", HFILL } },
+        { &hf_ppi_vector_vel_t,
+          { "Vel-t", "ppi_vector.vel_t",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Velocity-Total", HFILL } },
+
+        { &hf_ppi_vector_acc_r,
+          { "Accel-r", "ppi_vector.acc_r",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Acceleration-right", HFILL } },
+        { &hf_ppi_vector_acc_f,
+          { "Accel-f", "ppi_vector.acc_f",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Acceleration-forward", HFILL } },
+        { &hf_ppi_vector_acc_u,
+          { "Accel-u", "ppi_vector.acc_u",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Acceleration-up", HFILL } },
+        { &hf_ppi_vector_acc_t,
+          { "Accel-t", "ppi_vector.acc_t",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Acceleration-Total", HFILL } },
+
+        { &hf_ppi_vector_err_rot,
+          { "Err-Rot", "ppi_vector.err_rot",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Rotation margin of error", HFILL } },
+        { &hf_ppi_vector_err_off,
+          { "Err-Off", "ppi_vector.err_off",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Offset margin of  error", HFILL } },
+        { &hf_ppi_vector_err_vel,
+          { "Err-Vel", "ppi_vector.err_vel",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Velocity margin of error", HFILL } },
+        { &hf_ppi_vector_err_acc,
+          { "Err-Accel", "ppi_vector.err_acc",
+            FT_FLOAT, BASE_NONE, NULL, 0x0,
+            "Acceleration margin of error", HFILL } },
+
+        { &hf_ppi_vector_descstr,
+          { "Description", "ppi_vector.descr",
+            FT_STRING,  BASE_NONE, NULL, 0x0,
+            "Description", HFILL } } ,
+        { &hf_ppi_vector_appspecific_num,
+          { "Application Specific id", "ppi_vector.appid",
+            FT_UINT32, BASE_HEX, NULL, 0x0,
+            "application specific identifier", HFILL } },
+        { &hf_ppi_vector_appspecific_data,
+          { "Application specific data", "ppi_vector.appdata",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            "application specific data", HFILL } },
+
+        /*  There are currently only three vector flags.
+         *  These control the units/interpreration of a vector
+         */
+#define PPI_VECTOR_VFLAGS_DEFINES_FORWARD      0x00000001
+#define PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE                0x00000002
+#define PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS  0x00000004
+        /* Boolean vector flags */
+        { &hf_ppi_vector_vflags_defines_forward,
+          { "Defines forward", "ppi_vector.vflags.forward",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_DEFINES_FORWARD,
+            "Current vector indicates forward frame of reference", HFILL } },
+        { &hf_ppi_vector_vflags_rots_absolute,
+          { "Absolute (E/N/U)  rotations", "ppi_vector.vflags.abs_rots",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE,
+            "Rotations are in East/North/Up coord. sys", HFILL } },
+        { &hf_ppi_vector_vflags_offsets_from_gps,
+          { "Offsets from prev GPS TAG", "ppi_vector.vflags.offsets_from_gps",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS,
+            "Offsets fied rel. to Curr_Gps", HFILL } },
+
+        /*  There are currently eight vector characteristics.
+         *  These are purely descriptive (no mathematical importance)
+         */
+#define PPI_VECTOR_VCHARS_ANTENNA              0x00000001
+#define PPI_VECTOR_VCHARS_DIR_OF_TRAVEL                0x00000002
+#define PPI_VECTOR_VCHARS_FRONT_OF_VEH      0x00000004
+
+#define PPI_VECTOR_VCHARS_GPS_DERIVED       0x00000100
+#define PPI_VECTOR_VCHARS_INS_DERIVED       0x00000200
+#define PPI_VECTOR_VCHARS_COMPASS_DERIVED   0x00000400
+#define PPI_VECTOR_VCHARS_ACCELEROMETER_DERIVED  0x00000800
+#define PPI_VECTOR_VCHARS_HUMAN_DERIVED     0x00001000
+        /* Boolean vector chars */
+        { &hf_ppi_vector_vchars_antenna,
+          { "Antenna", "ppi_vector.chars.antenna",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_ANTENNA,
+            "Vector represents: Antenna", HFILL } },
+
+        { &hf_ppi_vector_vchars_dir_of_travel,
+          { "Dir of travel", "ppi_vector.chars.dir_of_travel",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_DIR_OF_TRAVEL,
+            "Vector represents: Direction of travel", HFILL } },
+
+        { &hf_ppi_vector_vchars_front_of_veh,
+          { "Front of vehicle", "ppi_vector.chars.front_of_veh",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_FRONT_OF_VEH,
+            "Vector represents: Front of vehicle", HFILL } },
+
+        { &hf_ppi_vector_vchars_gps_derived,
+          { "GPS Derived", "ppi_vector.vflags.gps_derived",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_GPS_DERIVED,
+            "Vector derived from: gps", HFILL } },
+
+        { &hf_ppi_vector_vchars_ins_derived,
+          { "INS Derived", "ppi_vector.vflags.ins_derived",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_INS_DERIVED,
+            "Vector derived from: inertial nav system", HFILL } },
+
+        { &hf_ppi_vector_vchars_compass_derived,
+          { "Compass derived", "ppi_vector.vflags.compass_derived",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_COMPASS_DERIVED,
+            "Vector derived from: compass", HFILL } },
+
+        { &hf_ppi_vector_vchars_accelerometer_derived,
+          { "Accelerometer derived", "ppi_vector.vflags.accelerometer_derived",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_ACCELEROMETER_DERIVED,
+            "Vector derived from: accelerometer", HFILL } },
+
+        { &hf_ppi_vector_vchars_human_derived,
+          { "Human derived", "ppi_vector.vflags.human_derived",
+            FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_HUMAN_DERIVED,
+            "Vector derived from: human", HFILL } },
+
+    };
+    static gint *ett[] = {
+        &ett_ppi_vector,
+        &ett_ppi_vector_present,
+        &ett_ppi_vectorflags,
+        &ett_ppi_vectorchars
+    };
+
+    proto_ppi_vector = proto_register_protocol("PPI vector decoder", "PPI vector Decoder", "ppi_vector");
+    proto_register_field_array(proto_ppi_vector, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+    register_dissector("ppi_vector", dissect_ppi_vector, proto_ppi_vector);
+
+}
+void dissect_ppi_vector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+    proto_tree *ppi_vector_tree = NULL;
+    proto_tree *vectorflags_tree = NULL;
+    proto_tree *vectorchars_tree = NULL;
+    proto_tree *my_pt, *pt, *present_tree = NULL;
+    proto_item *ti = NULL;
+    guint length_remaining;
+    int offset = 0;
+
+
+
+    /* bits */
+    int bit;
+    guint32 present, next_present;
+    /* values actually read out, for displaying */
+    guint32 version;
+    guint length;
+    gdouble rot_x, rot_y, rot_z;
+    gdouble off_r, off_f, off_u;
+    gdouble vel_r, vel_f, vel_u, vel_t;
+    gdouble acc_r, acc_f, acc_u, acc_t = 0;
+    gdouble err_rot, err_off, err_vel, err_acc;
+    char *curr_str; /* for description str */
+    guint32  appsecific_num; /* appdata parser should add a subtree based on this value */
+    guint32 flags=0, chars=0;
+
+    /* temporary, conversion values */
+    guint32 t_val;
+
+
+    /* Clear out stuff in the info column */
+    if (check_col(pinfo->cinfo,COL_INFO)) {
+        col_clear(pinfo->cinfo,COL_INFO);
+    }
+    version = tvb_get_guint8(tvb, offset);
+    length = tvb_get_letohs(tvb, offset+2);
+    present = tvb_get_letohl(tvb, offset+4);
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_Vector Capture v%u, Length %u",
+                     version, length);
+
+    /* Dissect the packet */
+    if (tree) {
+        ti = proto_tree_add_protocol_format(tree, proto_ppi_vector,
+                                            tvb, 0, length, "PPI Vector Header v%u, Length %u", version, length);
+        ppi_vector_tree= proto_item_add_subtree(ti, ett_ppi_vector);
+        proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_version,
+                            tvb, offset, 1, version);
+        proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_pad,
+                            tvb, offset + 1, 1, FALSE);
+        ti = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_length,
+                                 tvb, offset + 2, 2, length);
+    }
+    length_remaining = length;
+
+    /*
+     * FIXME: This only works if there is exactly 1 it_present
+     *        field in the header
+     */
+    if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
+        /*
+         * Radiotap header is shorter than the fixed-length portion
+         * plus one "present" bitset.
+         */
+        if (tree)
+            proto_item_append_text(ti, " (bogus - minimum length is 8)");
+        return;
+    }
+    /* Subtree for the "present flags" bitfield. */
+    if (tree) {
+        pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_present,
+                                 tvb, offset + 4, 4, present);
+        present_tree = proto_item_add_subtree(pt, ett_ppi_vector_present);
+
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vflags, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vchars, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_val_x, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_val_y, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_val_z, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_off_r, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_off_f, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_off_u, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vel_r, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vel_f, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vel_u, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_vel_t, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_acc_r, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_acc_f, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_acc_u, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_acc_t, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_err_rot, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_err_off, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_err_vel, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_err_acc, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_descstr, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_presenappsecific_num, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_appspecific_data, tvb, 4, 4, TRUE);
+        proto_tree_add_item(present_tree, hf_ppi_vector_present_ext, tvb, 4, 4, TRUE);
+    }
+    offset += PPI_GEOBASE_MIN_HEADER_LEN;
+    length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;
+
+
+    /* Now all of the fixed length, fixed location stuff is over. Loop over the bits */
+    for (; present; present = next_present) {
+        /* clear the least significant bit that is set */
+        next_present = present & (present - 1);
+        /* extract the least significant bit that is set */
+        bit = BITNO_32(present ^ next_present);
+        switch (bit) {
+        case  PPI_VECTOR_VFLAGS:
+            if (length_remaining < 4)
+                break;
+            flags =  tvb_get_letohl(tvb, offset);
+            if (tree) {
+                my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vflags, tvb, offset , 4, flags);
+                vectorflags_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorflags);
+
+                proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_defines_forward, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_rots_absolute, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_offsets_from_gps, tvb, offset, 4, TRUE);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_VCHARS:
+            if (length_remaining < 4)
+                break;
+            chars =  tvb_get_letohl(tvb, offset);
+            if (tree) {
+                my_pt = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_vchars, tvb, offset , 4, chars);
+                vectorchars_tree= proto_item_add_subtree(my_pt, ett_ppi_vectorchars);
+
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_antenna, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_dir_of_travel, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_front_of_veh, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_gps_derived, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_ins_derived, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_compass_derived, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_accelerometer_derived, tvb, offset, 4, TRUE);
+                proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_human_derived, tvb, offset, 4, TRUE);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ROTX:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            rot_x = fixed3_6_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_rot_x, tvb, offset, 4, rot_x);
+                if (flags &  PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
+                    proto_item_append_text(ti, " Degrees (Absolute)");
+                else
+                    proto_item_append_text(ti, " Degrees (Rel to forward)");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ROTY:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            rot_y = fixed3_6_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_rot_y, tvb, offset, 4, rot_y);
+                if (flags &  PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
+                    proto_item_append_text(ti, " Degrees (Absolute)");
+                else
+                    proto_item_append_text(ti, " Degrees (Rel to forward)");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ROTZ:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            rot_z =  fixed3_6_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_rot_z, tvb, offset, 4, rot_z);
+                if (flags &  PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE)
+                    proto_item_append_text(ti, " Degrees (Absolute) ");
+                else
+                    proto_item_append_text(ti, " Degrees (Rel to forward)");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_OFF_R:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            off_r = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_off_r, tvb, offset, 4, off_r);
+                if (flags &  PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
+                    proto_item_append_text(ti, " m from Curr_GPS");
+                else
+                    proto_item_append_text(ti, " m from Curr_Pos");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_OFF_F:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            off_f = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_off_f, tvb, offset, 4, off_f);
+                if (flags &  PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
+                    proto_item_append_text(ti, " m from Curr_GPS");
+                else
+                    proto_item_append_text(ti, " m from Curr_Pos");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_OFF_U:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            off_u = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_off_u, tvb, offset, 4, off_u);
+                if (flags &  PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS)
+                    proto_item_append_text(ti, " m from Curr_GPS");
+                else
+                    proto_item_append_text(ti, " m from Curr_Pos");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_VEL_R:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            vel_r = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_vel_r, tvb, offset, 4, vel_r);
+                proto_item_append_text(ti, " m/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_VEL_F:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            vel_f = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_vel_f, tvb, offset, 4, vel_f);
+                proto_item_append_text(ti, " m/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_VEL_U:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            vel_u = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_vel_u, tvb, offset, 4, vel_u);
+                proto_item_append_text(ti, " m/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_VEL_T:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            vel_t = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_vel_t, tvb, offset, 4, vel_t);
+                proto_item_append_text(ti, " m/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ACC_R:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            acc_r = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_acc_r, tvb, offset, 4, acc_r);
+                proto_item_append_text(ti, " (m/s)/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ACC_F:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            acc_f = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_acc_f, tvb, offset, 4, acc_f);
+                proto_item_append_text(ti, " (m/s)/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ACC_U:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            acc_u = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_acc_u, tvb, offset, 4, acc_u);
+                proto_item_append_text(ti, " (m/s)/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ACC_T:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            acc_t = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_acc_t, tvb, offset, 4, acc_t);
+                proto_item_append_text(ti, " (m/s)/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ERR_ROT:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            err_rot  = fixed3_6_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_err_rot, tvb, offset, 4, err_rot);
+                proto_item_append_text(ti, " degrees");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ERR_OFF:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            err_off  = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_err_off, tvb, offset, 4, err_off);
+                proto_item_append_text(ti, " meters");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ERR_VEL:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            err_vel  = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_err_vel, tvb, offset, 4, err_vel);
+                proto_item_append_text(ti, "m/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_ERR_ACC:
+            if (length_remaining < 4)
+                break;
+            t_val = tvb_get_letohl(tvb, offset);
+            err_acc  = fixed6_4_to_gdouble(t_val);
+            if (tree) {
+                ti = proto_tree_add_float(ppi_vector_tree, hf_ppi_vector_err_acc, tvb, offset, 4, err_acc);
+                proto_item_append_text(ti, " (m/s)/s");
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_DESCSTR:
+            if (length_remaining < 32)
+                break;
+            if (tree) {
+                curr_str= (char *)  tvb_get_ptr(tvb, offset, 32);
+                proto_tree_add_string(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, curr_str);
+            }
+            offset+=32;
+            length_remaining-=32;
+            break;
+        case  PPI_VECTOR_APPID:
+            if (length_remaining < 4)
+                break;
+            appsecific_num  = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
+            if (tree) {
+                proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_appspecific_num, tvb, offset, 4, appsecific_num);
+            }
+            offset+=4;
+            length_remaining-=4;
+            break;
+        case  PPI_VECTOR_APPDATA:
+            if (length_remaining < 60)
+                break;
+            if (tree) {
+                proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_appspecific_data, tvb, offset, 60,  FALSE);
+            }
+            offset+=60;
+            length_remaining-=60;
+            break;
+
+        default:
+            /*
+             * This indicates a field whose size we do not
+             * know, so we cannot proceed.
+             */
+            proto_tree_add_text(ppi_vector_tree, tvb, offset, 0,  "Error: PPI-VECTOR: unknown bit (%d) set in present field.\n", bit);
+            next_present = 0;
+            continue;
+        }
+
+    };
+    return;
+}
+
+
index 67d75ce839e37752ba519267130e56533b0a204e..4c92819ed279ba09910745a204b97bb69c5df2b1 100644 (file)
@@ -46,6 +46,7 @@
  *     May 7, 2008 - Added 'Aggregation Extension' and '802.3 Extension'
  */
 
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
  *     guint16 pfh_type;        // Type
  *     guint16 pfh_datalen;     // Length of data
  * } ppi_fieldheader_t;
+ *
+ * Anyone looking to add their own PPI dissector  would probably do well to imitate the GPS 
+ * ones seperation into a distinct file.  Here is a step by step guide:
+ * 1) add the number you received to the enum ppi_field_type declaration. 
+ * 2) Add a value string for your number into vs_ppi_field_type
+ * 3) declare a dissector handle by the ppi_gps_handle, and initialize it inside proto_reg_handoff
+ * 4) add  case inside dissect_ppi to call your new handle.
+ * 5) Write your parser, and get it loaded.
+ * Following these steps will result in less churn inside the ppi proper parser, and avoid namespace issues.
  */
 
+
 #define PPI_PADDED (1 << 0)
 
 #define PPI_V0_HEADER_LEN 8
@@ -167,10 +178,13 @@ typedef enum {
     /* 11 - 29999: RESERVED */
 
     /* 30000 - 65535: Private types */
-    INTEL_CORP_PRIVATE          = 30000,
-    MOHAMED_THAGA_PRIVATE       = 30001,
-    GPS_TAGGING_PRIVATE         = 30002,
-    CACE_PRIVATE                = 0xCACE
+    INTEL_CORP_PRIVATE           = 30000,
+    MOHAMED_THAGA_PRIVATE        = 30001,
+    PPI_GPS_INFO                 = 30002, /* 30002 - 30005 described in PPI-GEOLOCATION specifcation */
+    PPI_VECTOR_INFO              = 30003, /* currently available in draft from. jellch@harris.com */
+    PPI_HARRIS_TEST0             = 30004, /* 30004 is used for testing geolocation tag enhancements */
+    PPI_ANTENNA_INFO             = 30005,
+    CACE_PRIVATE                 = 0xCACE
     /* All others RESERVED.  Contact the WinPcap team for an assignment */
 } ppi_field_type;
 
@@ -308,6 +322,8 @@ static gint ett_8023_extension_errors = -1;
 
 static dissector_handle_t data_handle;
 static dissector_handle_t ieee80211_ht_handle;
+static dissector_handle_t ppi_gps_handle, ppi_vector_handle, ppi_harris_test_handle, ppi_antenna_handle;
+
 
 static const true_false_string tfs_ppi_head_flag_alignment = { "32-bit aligned", "Not aligned" };
 static const true_false_string tfs_tsft_ms = { "milliseconds", "microseconds" };
@@ -327,7 +343,10 @@ static const value_string vs_ppi_field_type[] = {
 
     {INTEL_CORP_PRIVATE, "Intel Corporation (private)"},
     {MOHAMED_THAGA_PRIVATE, "Mohamed Thaga (private)"},
-    {GPS_TAGGING_PRIVATE, "GPS Tagging (private)"},
+    {PPI_GPS_INFO, "GPS Tagging"},
+    {PPI_VECTOR_INFO, "Vector Tagging"},
+    {PPI_HARRIS_TEST0, "Harris geolocation-tag development"},
+    {PPI_ANTENNA_INFO, "Antenna Tagging"},
     {CACE_PRIVATE, "CACE Technologies (private)"},
     {0, NULL}
 };
@@ -813,6 +832,58 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             case PPI_8023_EXTENSION:
                 dissect_8023_extension(tvb, pinfo, ppi_tree, offset, data_len);
                 break;
+                       case PPI_GPS_INFO:
+                               if (ppi_gps_handle == NULL)
+                               {
+                                       proto_tree_add_text(ppi_tree, tvb, offset, data_len,
+                                       "%s (%u bytes)", val_to_str(data_type, (value_string *)&vs_ppi_field_type, "GPS: "), data_len);
+                               }
+                               else /* we found a suitable dissector */
+                               {
+                                       /* skip over the ppi_fieldheader, and pass it off to the dedicated GPS dissetor */
+                                       next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
+                                       call_dissector(ppi_gps_handle, next_tvb, pinfo, ppi_tree);
+                               }
+                               break;
+                       case PPI_VECTOR_INFO:
+                               if (ppi_vector_handle == NULL)
+                               {
+                                       proto_tree_add_text(ppi_tree, tvb, offset, data_len,
+                                       "%s (%u bytes)", val_to_str(data_type, (value_string *)&vs_ppi_field_type, "VECTOR: "), data_len);
+                               }
+                               else /* we found a suitable dissector */
+                               {
+                                       /* skip over the ppi_fieldheader, and pass it off to the dedicated VECTOR dissetor */
+                                       next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
+                                       call_dissector(ppi_vector_handle, next_tvb, pinfo, ppi_tree);
+                               }
+                               break;
+                       case PPI_HARRIS_TEST0:
+                               if (ppi_harris_test_handle == NULL)
+                               {
+                                       proto_tree_add_text(ppi_tree, tvb, offset, data_len,
+                                       "%s (%u bytes)", val_to_str(data_type, (value_string *)&vs_ppi_field_type, "HARRIS: "), data_len);
+                               }
+                               else /* we found a suitable dissector */
+                               {
+                                       /* skip over the ppi_fieldheader, and pass it off to the dedicated ANTENNA_ORIENTATION dissetor */
+                                       next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
+                                       call_dissector(ppi_harris_test_handle, next_tvb, pinfo, ppi_tree);
+                               }
+                               break;
+                       case PPI_ANTENNA_INFO:
+                               if (ppi_antenna_handle == NULL)
+                               {
+                                       proto_tree_add_text(ppi_tree, tvb, offset, data_len,
+                                       "%s (%u bytes)", val_to_str(data_type, (value_string *)&vs_ppi_field_type, "ANTENNA: "), data_len);
+                               }
+                               else /* we found a suitable dissector */
+                               {
+                                       /* skip over the ppi_fieldheader, and pass it off to the dedicated ANTENNA dissetor */
+                                       next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
+                                       call_dissector(ppi_antenna_handle, next_tvb, pinfo, ppi_tree);
+                               }
+                               break;
 
             default:
                 if (tree)
@@ -1291,6 +1362,10 @@ proto_reg_handoff_ppi(void)
     ppi_handle = create_dissector_handle(dissect_ppi, proto_ppi);
     data_handle = find_dissector("data");
     ieee80211_ht_handle = find_dissector("wlan_ht");
+       ppi_gps_handle = find_dissector("ppi_gps");
+       ppi_vector_handle = find_dissector("ppi_vector");
+       ppi_harris_test_handle = find_dissector("ppi_harris_test");
+       ppi_antenna_handle = find_dissector("ppi_antenna");
 
     dissector_add("wtap_encap", WTAP_ENCAP_PPI, ppi_handle);
 }