/* packet-ppi-vector.c * Routines for PPI-GEOLOCATION-VECTOR dissection * Copyright 2010, Harris Corp, jellch@harris.com * * See * * http://new.11mercenary.net/~johnycsh/ppi_geolocation_spec/ * * for specifications. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * Copied from packet-radiotap.c * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #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, /* V1 */ 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, /* V2 */ PPI_VECTOR_OFF_X = 5, PPI_VECTOR_OFF_Y = 6, PPI_VECTOR_OFF_Z = 7, PPI_VECTOR_ERR_ROT = 16, PPI_VECTOR_ERR_OFF = 17, /* V1 only */ 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 }; #define PPI_VECTOR_MAXTAGLEN 144 /* increase as fields are added */ /* 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_AOA 0x00000008 #define PPI_VECTOR_VCHARS_TRANSMITTER_POS 0x00000010 #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 #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 /* V1 */ #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 /* V2 */ #define PPI_VECTOR_MASK_OFF_X 0x00000020 #define PPI_VECTOR_MASK_OFF_Y 0x00000040 #define PPI_VECTOR_MASK_OFF_Z 0x00000080 #define PPI_VECTOR_MASK_ERR_ROT 0x00010000 #define PPI_VECTOR_MASK_ERR_OFF 0x00020000 /* V1 only */ #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 */ /* There are currently only three vector flags. * These control the units/interpretation of a vector */ #define PPI_VECTOR_VFLAGS_DEFINES_FORWARD 0x00000001 /* V1 */ #define PPI_VECTOR_VFLAGS_ROTS_ABSOLUTE 0x00000002 #define PPI_VECTOR_VFLAGS_OFFSETS_FROM_GPS 0x00000004 /* V2 */ #define PPI_VECTOR_VFLAGS_RELATIVE_TO 0x00000006 /* 2 bits */ /* Values for the two-bit RelativeTo subfield of vflags */ static const value_string relativeto_string[] = { { 0x00, "Forward"}, { 0x01, "Earth"}, { 0x02, "Current"}, { 0x03, "Reserved"}, { 0x00, NULL} }; void proto_register_ppi_vector(void); /* protocol */ static int proto_ppi_vector; /* "top" level fields */ static int hf_ppi_vector_version; static int hf_ppi_vector_pad; static int hf_ppi_vector_length; static int hf_ppi_vector_present; static int hf_ppi_vector_vflags; static int hf_ppi_vector_vchars; static int hf_ppi_vector_rot_x; static int hf_ppi_vector_rot_y; static int hf_ppi_vector_rot_z; /* V1 */ static int hf_ppi_vector_off_r; static int hf_ppi_vector_off_f; static int hf_ppi_vector_off_u; static int hf_ppi_vector_vel_r; static int hf_ppi_vector_vel_f; static int hf_ppi_vector_vel_u; static int hf_ppi_vector_vel_t; static int hf_ppi_vector_acc_r; static int hf_ppi_vector_acc_f; static int hf_ppi_vector_acc_u; static int hf_ppi_vector_acc_t; /* V2 */ static int hf_ppi_vector_off_x; static int hf_ppi_vector_off_y; static int hf_ppi_vector_off_z; static int hf_ppi_vector_err_rot; static int hf_ppi_vector_err_off; /* V1 only */ static int hf_ppi_vector_err_vel; static int hf_ppi_vector_err_acc; static int hf_ppi_vector_descstr; static int hf_ppi_vector_appspecific_num; static int hf_ppi_vector_appspecific_data; /* "Present" flags */ static int hf_ppi_vector_present_vflags; static int hf_ppi_vector_present_vchars; static int hf_ppi_vector_present_val_x; static int hf_ppi_vector_present_val_y; static int hf_ppi_vector_present_val_z; /* V1 */ static int hf_ppi_vector_present_off_r; static int hf_ppi_vector_present_off_f; static int hf_ppi_vector_present_off_u; static int hf_ppi_vector_present_vel_r; static int hf_ppi_vector_present_vel_f; static int hf_ppi_vector_present_vel_u; static int hf_ppi_vector_present_vel_t; static int hf_ppi_vector_present_acc_r; static int hf_ppi_vector_present_acc_f; static int hf_ppi_vector_present_acc_u; static int hf_ppi_vector_present_acc_t; /* V2 */ static int hf_ppi_vector_present_off_x; static int hf_ppi_vector_present_off_y; static int hf_ppi_vector_present_off_z; static int hf_ppi_vector_present_err_rot; static int hf_ppi_vector_present_err_off; /* V1 only */ static int hf_ppi_vector_present_err_vel; static int hf_ppi_vector_present_err_acc; static int hf_ppi_vector_present_descstr; static int hf_ppi_vector_presenappsecific_num; static int hf_ppi_vector_present_appspecific_data; static int hf_ppi_vector_present_ext; /* VectorFlags bits */ /* There are currently only three bits and two fields defined in vector flags. * These control the units/interpretation of a vector */ static int hf_ppi_vector_vflags_defines_forward; /* bit 0 */ /* V1 */ static int hf_ppi_vector_vflags_rots_absolute; /* different ways to display the same bit, hi or low */ static int hf_ppi_vector_vflags_offsets_from_gps; /* these are different ways to display the same bit, hi or low */ /* V2 */ static int hf_ppi_vector_vflags_relative_to; /* bits 1 and 2 */ /* There are currently eight vector characteristics. * These are purely descriptive (no mathematical importance) */ static int hf_ppi_vector_vchars_antenna; static int hf_ppi_vector_vchars_dir_of_travel; static int hf_ppi_vector_vchars_front_of_veh; /* V2 only */ static int hf_ppi_vector_vchars_angle_of_arrival; static int hf_ppi_vector_vchars_transmitter_pos; static int hf_ppi_vector_vchars_gps_derived; static int hf_ppi_vector_vchars_ins_derived; static int hf_ppi_vector_vchars_compass_derived; static int hf_ppi_vector_vchars_accelerometer_derived; static int hf_ppi_vector_vchars_human_derived; static int hf_ppi_vector_unknown_data; /*These represent arrow-dropdownthings in the gui */ static int ett_ppi_vector; static int ett_ppi_vector_present; static int ett_ppi_vectorflags; static int ett_ppi_vectorchars; static expert_field ei_ppi_vector_present_bit; static expert_field ei_ppi_vector_length; /* We want to abbreviate this field into a single line. Does so without any string manipulation */ static void annotate_vector_chars(uint32_t chars, proto_tree *my_pt) { if (chars & PPI_VECTOR_VCHARS_ANTENNA) proto_item_append_text(my_pt, " (Antenna)"); if (chars & PPI_VECTOR_VCHARS_DIR_OF_TRAVEL) proto_item_append_text(my_pt, " (DOT)"); if (chars & PPI_VECTOR_VCHARS_FRONT_OF_VEH) proto_item_append_text(my_pt, " (Front_of_veh)"); if (chars & PPI_VECTOR_VCHARS_AOA) proto_item_append_text(my_pt, " (AOA)"); if (chars & PPI_VECTOR_VCHARS_TRANSMITTER_POS) proto_item_append_text(my_pt, " (TRANSMITTER_POS)"); } static void dissect_ppi_vector_v1(tvbuff_t *tvb, packet_info *pinfo, int offset, int length_remaining, proto_tree *ppi_vector_tree) { proto_tree *vectorflags_tree = NULL; proto_tree *vectorchars_tree = NULL; proto_tree *my_pt, *pt; proto_item *ti; /* bits */ int bit; uint32_t present, next_present; /* values actually read out, for displaying */ double rot_x, rot_y, rot_z; double off_r, off_f, off_u; double vel_r, vel_f, vel_u, vel_t; double acc_r, acc_f, acc_u, acc_t = 0; double err_rot, err_off, err_vel, err_acc; uint32_t appsecific_num; /* appdata parser should add a subtree based on this value */ uint32_t flags=0, chars=0; static int * const ppi_vector_present_flags[] = { &hf_ppi_vector_present_vflags, &hf_ppi_vector_present_vchars, &hf_ppi_vector_present_val_x, &hf_ppi_vector_present_val_y, &hf_ppi_vector_present_val_z, &hf_ppi_vector_present_off_r, &hf_ppi_vector_present_off_f, &hf_ppi_vector_present_off_u, &hf_ppi_vector_present_vel_r, &hf_ppi_vector_present_vel_f, &hf_ppi_vector_present_vel_u, &hf_ppi_vector_present_vel_t, &hf_ppi_vector_present_acc_r, &hf_ppi_vector_present_acc_f, &hf_ppi_vector_present_acc_u, &hf_ppi_vector_present_acc_t, &hf_ppi_vector_present_err_rot, &hf_ppi_vector_present_err_off, &hf_ppi_vector_present_err_vel, &hf_ppi_vector_present_err_acc, &hf_ppi_vector_present_descstr, &hf_ppi_vector_presenappsecific_num, &hf_ppi_vector_present_appspecific_data, &hf_ppi_vector_present_ext, NULL }; /* temporary, conversion values */ uint32_t t_val; present = tvb_get_letohl(tvb, offset+4); /* Subtree for the "present flags" bitfield. */ pt = proto_tree_add_bitmask(ppi_vector_tree, tvb, offset + 4, hf_ppi_vector_present, ett_ppi_vector_present, ppi_vector_present_flags, ENC_LITTLE_ENDIAN); 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 (ppi_vector_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, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_rots_absolute, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_offsets_from_gps, tvb, offset, 4, ENC_LITTLE_ENDIAN); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_VCHARS: if (length_remaining < 4) break; chars = tvb_get_letohl(tvb, offset); if (ppi_vector_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, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_dir_of_travel, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_front_of_veh, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_gps_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_ins_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_compass_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_accelerometer_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_human_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_ROTX: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); rot_x = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_r, tvb, offset, 4, vel_r); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_f, tvb, offset, 4, vel_f); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_u, tvb, offset, 4, vel_u); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_vel_t, tvb, offset, 4, vel_t); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_r, tvb, offset, 4, acc_r); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_f, tvb, offset, 4, acc_f); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_u, tvb, offset, 4, acc_u); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_acc_t, tvb, offset, 4, acc_t); 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 = ppi_fixed3_6_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_rot, tvb, offset, 4, err_rot); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_off, tvb, offset, 4, err_off); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_vel, tvb, offset, 4, err_vel); 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 = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(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; proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, ENC_ASCII); 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 */ 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; proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_appspecific_data, tvb, offset, 60, ENC_NA); offset+=60; length_remaining-=60; break; default: /* * This indicates a field whose size we do not * know, so we cannot proceed. */ expert_add_info_format(pinfo, pt, &ei_ppi_vector_present_bit, "Error: PPI-VECTOR: unknown bit (%d) set in present field.", bit); next_present = 0; continue; } } } static void dissect_ppi_vector_v2(tvbuff_t *tvb, packet_info *pinfo, int offset, int length_remaining, proto_tree *ppi_vector_tree, proto_item *vector_line) { proto_tree *vectorflags_tree = NULL; proto_tree *vectorchars_tree = NULL; proto_tree *my_pt, *pt; proto_item *ti; /* bits */ int bit; uint32_t present, next_present; /* values actually read out, for displaying */ char *curr_str; /* these are used to specially handle RelativeTo: */ uint32_t relativeto_int; const char *relativeto_str; /* normal fields*/ uint32_t flags=0, chars=0; double rot_x, rot_y, rot_z; double off_x, off_y, off_z; double err_rot, err_off; uint32_t appsecific_num; /* appdata parser should add a subtree based on this value */ static int * const ppi_vector_present_flags[] = { &hf_ppi_vector_present_vflags, &hf_ppi_vector_present_vchars, &hf_ppi_vector_present_val_x, &hf_ppi_vector_present_val_y, &hf_ppi_vector_present_val_z, &hf_ppi_vector_present_off_x, &hf_ppi_vector_present_off_y, &hf_ppi_vector_present_off_z, &hf_ppi_vector_present_err_rot, &hf_ppi_vector_present_err_off, &hf_ppi_vector_present_descstr, &hf_ppi_vector_presenappsecific_num, &hf_ppi_vector_present_appspecific_data, &hf_ppi_vector_present_ext, NULL }; /* temporary, conversion values */ uint32_t t_val; present = tvb_get_letohl(tvb, offset+4); /* Subtree for the "present flags" bitfield. */ pt = proto_tree_add_bitmask(ppi_vector_tree, tvb, offset + 4, hf_ppi_vector_present, ett_ppi_vector_present, ppi_vector_present_flags, ENC_LITTLE_ENDIAN); offset += PPI_GEOBASE_MIN_HEADER_LEN; length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN; /* Before we process any fields, we check what this vector is RelativeTo. */ /* We do this so this up front so that it displays prominently in the summary line */ /* Another reason to do this up here is that vflags may not be present (in which case it defaults to 0) */ /* It also saves us from repeating this logic in any of the individual fields */ if ( (present & PPI_VECTOR_MASK_VFLAGS) && length_remaining >= 4) { /*vflags is the first field, */ flags = tvb_get_letohl(tvb, offset); relativeto_int = (flags & (PPI_VECTOR_VFLAGS_RELATIVE_TO)); /* mask out all other bits */ relativeto_int = relativeto_int >> 1; /*scoot over 1 bit to align with the type string */ relativeto_str = val_to_str_const (relativeto_int, relativeto_string, "Reserved"); /*re-use that type string up top */ /* We will append this text to the vector line once all the other fields have processed */ /* this is important enough to put in vector line */ if (flags & PPI_VECTOR_VFLAGS_DEFINES_FORWARD) proto_item_append_text(vector_line, " (Forward)"); /* Intentionally don't upset offset, length_remaining. This is taken care of in the normal vflags parser below*/ } else /* No vflags means vlfags defaults to zero. RelativeTo: Forward */ { relativeto_str = " RelativeTo: Forward"; } /* * vchars is another field that we want to pre-process similar to vflags and for the same reasons. * we perform separate length checks depending on if vector_flags is present (which would precede vector_chars) */ if ( ( (present & PPI_VECTOR_MASK_VFLAGS)) && (present & PPI_VECTOR_MASK_VCHARS) && length_remaining >= 8) chars = tvb_get_letohl(tvb, offset + 4); else if ( (!(present & PPI_VECTOR_MASK_VFLAGS)) && (present & PPI_VECTOR_MASK_VCHARS) && length_remaining >= 4) chars = tvb_get_letohl(tvb, offset ); if (chars) { /* Mark the most interesting characteristics on the vector dropdown line */ annotate_vector_chars(chars, vector_line); /* Intentionally don't update offset, length_remaining. This is taken care of in the normal vchars parser below*/ } /* 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); */ /* Usually we read this in, but vflags is a special case handled above */ if (ppi_vector_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, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorflags_tree, hf_ppi_vector_vflags_relative_to, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (flags & PPI_VECTOR_VFLAGS_DEFINES_FORWARD) proto_item_append_text(vectorflags_tree, " (Forward)"); proto_item_append_text (vectorflags_tree, " RelativeTo: %s", relativeto_str); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_VCHARS: if (length_remaining < 4) break; /* chars = tvb_get_letohl(tvb, offset); */ /*Usually we read this in, but vchars specially handled above */ if (ppi_vector_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, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_dir_of_travel, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_front_of_veh, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_angle_of_arrival, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_transmitter_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_gps_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_ins_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_compass_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_accelerometer_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(vectorchars_tree, hf_ppi_vector_vchars_human_derived, tvb, offset, 4, ENC_LITTLE_ENDIAN); annotate_vector_chars(chars, my_pt); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_ROTX: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); rot_x = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_x, tvb, offset, 4, rot_x); proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Pitch:%3f ", rot_x); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_ROTY: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); rot_y = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_y, tvb, offset, 4, rot_y); proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Roll:%3f ", rot_y); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_ROTZ: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); rot_z = ppi_fixed3_6_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_rot_z, tvb, offset, 4, rot_z); proto_item_append_text(ti, " Degrees RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Heading:%3f ", rot_z); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_OFF_X: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); off_x = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_x, tvb, offset, 4, off_x); proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Off-X:%3f ", off_x); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_OFF_Y: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); off_y = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_y, tvb, offset, 4, off_y); proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Off-Y:%3f ", off_y); } offset+=4; length_remaining-=4; break; case PPI_VECTOR_OFF_Z: if (length_remaining < 4) break; t_val = tvb_get_letohl(tvb, offset); off_z = ppi_fixed6_4_to_double(t_val); if (ppi_vector_tree) { ti = proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_off_z, tvb, offset, 4, off_z); proto_item_append_text(ti, " Meters RelativeTo: %s", relativeto_str); proto_item_append_text(vector_line, " Off-Z:%3f ", off_z); } 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 = ppi_fixed3_6_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_rot, tvb, offset, 4, err_rot); 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 = ppi_fixed6_4_to_double(t_val); proto_tree_add_double(ppi_vector_tree, hf_ppi_vector_err_off, tvb, offset, 4, err_off); offset+=4; length_remaining-=4; break; case PPI_VECTOR_DESCSTR: if (length_remaining < 32) break; if (ppi_vector_tree) { /* proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, ENC_ASCII); */ curr_str = tvb_format_stringzpad(pinfo->pool, tvb, offset, 32); /* need to append_text this */ proto_tree_add_string(ppi_vector_tree, hf_ppi_vector_descstr, tvb, offset, 32, curr_str); proto_item_append_text(vector_line, " (%s)", 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 (ppi_vector_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 (ppi_vector_tree) { proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_appspecific_data, tvb, offset, 60, ENC_NA); } offset+=60; length_remaining-=60; break; default: /* * This indicates a field whose size we do not * know, so we cannot proceed. */ expert_add_info_format(pinfo, pt, &ei_ppi_vector_present_bit, "Error: PPI-VECTOR: unknown bit (%d) set in present field.\n", bit); next_present = 0; continue; } } /* Append the RelativeTo string we computed up top */ proto_item_append_text (vector_line, " RelativeTo: %s", relativeto_str); } static int dissect_ppi_vector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_tree *ppi_vector_tree; proto_item *ti, *vector_line; int length_remaining; int offset = 0; /* values actually read out, for displaying */ uint32_t version; unsigned length; /* Clear out stuff in the info column */ col_clear(pinfo->cinfo,COL_INFO); /* pull out the first three fields of the BASE-GEOTAG-HEADER */ version = tvb_get_uint8(tvb, offset); length = tvb_get_letohs(tvb, offset+2); /* Setup basic column info */ col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_Vector Capture v%u, Length %u", version, length); /* Create the basic dissection tree*/ vector_line = proto_tree_add_protocol_format(tree, proto_ppi_vector, tvb, 0, length, "Vector:"); ppi_vector_tree = proto_item_add_subtree(vector_line, 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, ENC_LITTLE_ENDIAN); ti = proto_tree_add_uint(ppi_vector_tree, hf_ppi_vector_length, tvb, offset + 2, 2, length); /* initialize remaining length */ length_remaining = length; /* minimum length check, should atleast be a fixed-size geotagging-base header*/ if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) { /* * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion * plus one "present" bitset. */ expert_add_info_format(pinfo, ti, &ei_ppi_vector_length, "Invalid PPI-Vector length - minimum length is %d", PPI_GEOBASE_MIN_HEADER_LEN); return 2; } switch (version) { case 1: dissect_ppi_vector_v1(tvb, pinfo, offset, length_remaining, ppi_vector_tree); break; case 2: /* perform max length sanity checking */ if (length > PPI_VECTOR_MAXTAGLEN ) { expert_add_info_format(pinfo, ti, &ei_ppi_vector_length, "Invalid PPI-Vector length (got %d, %d max\n)", length, PPI_VECTOR_MAXTAGLEN); return 2; } dissect_ppi_vector_v2(tvb, pinfo, offset, length_remaining, ppi_vector_tree, vector_line); break; default: proto_tree_add_item(ppi_vector_tree, hf_ppi_vector_unknown_data, tvb, offset + 4, -1, ENC_NA); break; } return tvb_captured_length(tvb); } 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 } }, /* 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 characteristics", "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 } }, /* V1 */ { &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 } }, /* V2 */ { &hf_ppi_vector_present_off_x, { "Offset_R", "ppi_vector.present.off_x", FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_X, "Specifies if the offset-x (right/east) field is present", HFILL } }, { &hf_ppi_vector_present_off_y, { "Offset_F", "ppi_vector.present.off_y", FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_Y, "Specifies if the offset-y (forward/north) field is present", HFILL } }, { &hf_ppi_vector_present_off_z, { "Offset_U", "ppi_vector.present.off_z", FT_BOOLEAN, 32, NULL, PPI_VECTOR_MASK_OFF_Z, "Specifies if the offset-z (up) 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 } }, /* V1 only */ { &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_DOUBLE, BASE_NONE, NULL, 0x0, "Pitch (Rotation x) packet was received at", HFILL } }, { &hf_ppi_vector_rot_y, { "Roll", "ppi_vector.roll", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Roll (Rotation y) packet was received at", HFILL } }, { &hf_ppi_vector_rot_z, { "Heading", "ppi_vector.heading", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Heading (Rotation z) packet was received at", HFILL } }, /* V1 */ { &hf_ppi_vector_off_r, { "Off-r", "ppi_vector.off_r", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offset right", HFILL } }, { &hf_ppi_vector_off_f, { "Off-f", "ppi_vector.off_f", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offation forward", HFILL } }, { &hf_ppi_vector_off_u, { "Off-u", "ppi_vector.off_u", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offset up", HFILL } }, { &hf_ppi_vector_vel_r, { "Vel-r", "ppi_vector.vel_r", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec), 0x0, "Velocity-right", HFILL } }, { &hf_ppi_vector_vel_f, { "Vel-f", "ppi_vector.vel_f", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec), 0x0, "Velocity-forward", HFILL } }, { &hf_ppi_vector_vel_u, { "Vel-u", "ppi_vector.vel_u", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec), 0x0, "Velocity-up", HFILL } }, { &hf_ppi_vector_vel_t, { "Vel-t", "ppi_vector.vel_t", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec), 0x0, "Velocity-Total", HFILL } }, { &hf_ppi_vector_acc_r, { "Accel-r", "ppi_vector.acc_r", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec_squared), 0x0, "Acceleration-right", HFILL } }, { &hf_ppi_vector_acc_f, { "Accel-f", "ppi_vector.acc_f", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec_squared), 0x0, "Acceleration-forward", HFILL } }, { &hf_ppi_vector_acc_u, { "Accel-u", "ppi_vector.acc_u", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec_squared), 0x0, "Acceleration-up", HFILL } }, { &hf_ppi_vector_acc_t, { "Accel-t", "ppi_vector.acc_t", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec_squared), 0x0, "Acceleration-Total", HFILL } }, /* V2 */ { &hf_ppi_vector_off_x, { "Off-x", "ppi_vector.off_x", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offset-x (right/east)", HFILL } }, { &hf_ppi_vector_off_y, { "Off-y", "ppi_vector.off_y", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offset-y (forward/north)", HFILL } }, { &hf_ppi_vector_off_z, { "Off-z", "ppi_vector.off_z", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Offset-z (up)", HFILL } }, { &hf_ppi_vector_err_rot, { "Err-Rot", "ppi_vector.err_rot", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_degree_degrees), 0x0, "Rotation margin of error", HFILL } }, { &hf_ppi_vector_err_off, { "Err-Off", "ppi_vector.err_off", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_meters), 0x0, "Offset margin of error", HFILL } }, /* V1 only */ { &hf_ppi_vector_err_vel, { "Err-Vel", "ppi_vector.err_vel", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec), 0x0, "Velocity margin of error", HFILL } }, { &hf_ppi_vector_err_acc, { "Err-Accel", "ppi_vector.err_acc", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_sec_squared), 0x0, "Acceleration margin of error", HFILL } }, { &hf_ppi_vector_descstr, { "Description", "ppi_vector.descr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, 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 } }, /* 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 } }, /* V1 */ { &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 } }, /* V2 */ { &hf_ppi_vector_vflags_relative_to, { "RelativeTo", "ppi_vector.vflags.relative_to", FT_UINT32, BASE_HEX, VALS(relativeto_string), PPI_VECTOR_VFLAGS_RELATIVE_TO, "Reference frame vectors are RelativeTo:", HFILL } }, /* 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 } }, /* V2 only */ { &hf_ppi_vector_vchars_angle_of_arrival, { "Angle of arrival", "ppi_vector.chars.angle_of_arr", FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_AOA, "Vector represents: Angle of Arrival", HFILL } }, { &hf_ppi_vector_vchars_transmitter_pos, { "Transmitter Position", "ppi_vector.chars.transmitter_pos", FT_BOOLEAN, 32, NULL, PPI_VECTOR_VCHARS_TRANSMITTER_POS, "Vector position represents computed transmitter location", 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 } }, { &hf_ppi_vector_unknown_data, { "Data for unknown version", "ppi_vector.unknown_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, }; static int *ett[] = { &ett_ppi_vector, &ett_ppi_vector_present, &ett_ppi_vectorflags, &ett_ppi_vectorchars }; static ei_register_info ei[] = { { &ei_ppi_vector_present_bit, { "ppi_vector.present.unknown_bit", PI_PROTOCOL, PI_WARN, "Error: PPI-VECTOR: unknown bit set in present field.", EXPFILL }}, { &ei_ppi_vector_length, { "ppi_vector.length.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }}, }; expert_module_t* expert_ppi_vector; 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)); expert_ppi_vector = expert_register_protocol(proto_ppi_vector); expert_register_field_array(expert_ppi_vector, ei, array_length(ei)); register_dissector("ppi_vector", dissect_ppi_vector, proto_ppi_vector); } /* * 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: */