isi-wireshark-plugin/src/isi-gps.c

839 lines
35 KiB
C

/* isi-gps.c
* Dissector for ISI's Location resource
* Copyright 2010-2015, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* GPS Data Packet Reverse Engineered by Luke Dashjr <luke@dashjr.org>
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <epan/prefs.h>
#include <epan/packet.h>
#include "packet-isi.h"
#include "isi-gps.h"
/* centimeter per second to kilometer per hour */
#define CMS_TO_KMH 0.036
#define SAT_PKG_LEN 12
static const value_string isi_location_id[] = {
{0x00, "LS_LOCATION_REQ"},
{0x01, "LS_LOCATION_RESP"},
{0x02, "LS_LOCATION_NTF"},
{0x03, "LS_LOCATION_STOP_REQ"},
{0x04, "LS_LOCATION_STOP_RESP"},
{0x07, "LS_METHOD_INFORMATION_REQ"},
{0x08, "LS_METHOD_INFORMATION_RESP"},
{0x09, "LS_METHOD_INFORMATION_IND"},
{0x0A, "LS_SERVICE_REQUIRED_REQ"},
{0x0B, "LS_SERVICE_REQUIRED_RESP"},
{0x0C, "LS_SERVICE_REQUIRED_IND"},
{0x0D, "LS_PRIVACY_REGISTRATION_REQ"},
{0x0E, "LS_PRIVACY_REGISTRATION_RESP"},
{0x0F, "LS_PRIVACY_NTF"},
{0x10, "LS_PRIVACY_NOTIFICATION_RESULT_REQ"},
{0x11, "LS_PRIVACY_NOTIFICATION_RESULT_RESP"},
{0x12, "LS_METHOD_REGISTRATION_REQ"},
{0x13, "LS_METHOD_REGISTRATION_RESP"},
{0x14, "LS_METHOD_ASSISTANCE_REQ"},
{0x15, "LS_METHOD_ASSISTANCE_RESP"},
{0x20, "LS_NMEA_LISTENER_REQ"},
{0x21, "LS_NMEA_LISTENER_RESP"},
{0x22, "LS_NMEA_LISTENER_NTF"},
{0x30, "LS_CLEAR_GPS_DATA_REQ"},
{0x31, "LS_CLEAR_GPS_DATA_RESP"},
{0x32, "LS_PING_REQ"},
{0x33, "LS_PING_RESP"},
{0x34, "LS_PING_NTF"},
{0x36, "LS_LTM_TEST_REQ"},
{0x37, "LS_LTM_TEST_RESP"},
{0x38, "LS_LTM_TEST_NTF"},
{0x39, "LS_HW_CONN_TEST_REQ"},
{0x3A, "LS_HW_CONN_TEST_RESP"},
{0x40, "LS_GSM_PRIVACY_REQ"},
{0x41, "LS_GSM_PRIVACY_RESP"},
{0x42, "LS_GSM_PRIVACY_TIMEOUT_REQ"},
{0x43, "LS_GSM_PRIVACY_TIMEOUT_RESP"},
{0x44, "LS_GSM_LOCATE_REQ"},
{0x45, "LS_GSM_LOCATE_RESP"},
{0x50, "LS_SUPL_LISTENER_REGISTRATION_REQ"},
{0x51, "LS_SUPL_LISTENER_REGISTRATION_RESP"},
{0x52, "LS_SUPL_CREATE_SESSION_REQUEST_NTF"},
{0x53, "LS_SUPL_CREATE_SESSION_RESPONSE_NTF"},
{0x54, "LS_SUPL_SESSION_END_NTF"},
{0x55, "LS_SUPL_GET_SUPL_INFO_REQ"},
{0x56, "LS_SUPL_GET_SUPL_INFO_RESP"},
{0x57, "LS_SUPL_CANCEL_SUPL_INFO_REQ"},
{0x58, "LS_SUPL_CANCEL_SUPL_INFO_RESP"},
{0x59, "LS_SUPL_POS_NTF"},
{0x5A, "LS_SUPL_POS_ACK_NTF"},
{0x5B, "LS_SUPL_POS_END_NTF"},
{0x5C, "LS_SUPL_SESSION_STATUS_REQUEST_NTF"},
{0x5D, "LS_SUPL_SESSION_STATUS_RESPONSE_NTF"},
{0x5E, "LS_SUPL_POSITION_FIX_NTF"},
{0x60, "LS_WCDMA_LOCATE_REQ"},
{0x61, "LS_WCDMA_LOCATE_RESP"},
{0x62, "LS_WCDMA_LOCATE_NTF"},
{0x63, "LS_SOURCE_LIST_REQ"},
{0x64, "LS_SOURCE_LIST_RESP"},
{0x65, "LS_TRACKING_START_REQ"},
{0x66, "LS_TRACKING_START_RESP"},
{0x67, "LS_TRACKING_DATA_NTF"},
{0x68, "LS_TRACKING_STOP_REQ"},
{0x69, "LS_TRACKING_STOP_RESP"},
{0x70, "LS_POSITIONING_SUPPORT_REQ"},
{0x71, "LS_POSITIONING_SUPPORT_RESP"},
{0x72, "LS_POSITIONING_SUPPORT_NTF"},
{0x73, "LS_GPS_STATUS_REQ"},
{0x74, "LS_GPS_STATUS_RESP"},
{0x76, "LS_SUPL_ALLOWED_REQ"},
{0x77, "LS_SUPL_ALLOWED_RESP"},
{0x78, "LS_SENSOR_REGISTRATION_REQ"},
{0x79, "LS_SENSOR_REGISTRATION_RESP"},
{0x7A, "LS_SENSOR_EVENT_REQ"},
{0x7B, "LS_SENSOR_EVENT_RESP"},
{0x7C, "LS_SENSOR_NTF"},
{0x7D, "LS_GPS_STATUS_IND"},
{0x7E, "LS_SUPL_SERVER_CONF_REQ"},
{0x7F, "LS_SUPL_SERVER_CONF_RESP"},
{0x80, "LS_SUPL_NW_INIT_REQ"},
{0x81, "LS_SUPL_NW_INIT_RESP"},
{0x82, "LS_SOCKET_REGISTRATION_REQ"},
{0x83, "LS_SOCKET_REGISTRATION_RESP"},
{0x84, "LS_SOCKET_OPEN_REQUEST_NTF"},
{0x85, "LS_SOCKET_OPEN_RESPONSE_NTF"},
{0x86, "LS_SOCKET_SEND_REQUEST_NTF"},
{0x87, "LS_SOCKET_SEND_RESPONSE_NTF"},
{0x88, "LS_SOCKET_RECV_REQ"},
{0x89, "LS_SOCKET_RECV_RESP"},
{0x8A, "LS_SOCKET_CLOSE_REQUEST_NTF"},
{0x8B, "LS_SOCKET_CLOSE_RESPONSE_NTF"},
{0x8C, "LS_SOCKET_CLOSED_REQ"},
{0x8D, "LS_SOCKET_CLOSED_RESP"},
{0x90, "LS_HYBRID_TRACKING_REQ"},
{0x91, "LS_HYBRID_TRACKING_RESP"},
{0x92, "LS_HYBRID_TRACKING_NTF"},
{0xA0, "LS_GPS_ANTENNA_CTRL_REQ"},
{0xA1, "LS_GPS_ANTENNA_CTRL_RESP"},
{0xE0, "LS_DEBUG_REQ"},
{0xE1, "LS_DEBUG_RESP"},
{0x00, NULL }
};
static const value_string isi_location_sub_id[] = {
{0x0103, "LS_SB_PRIVACY"},
{0x0105, "LS_SB_JAVA_INFO"},
{0x0108, "LS_SB_CDMA_WAP_INFO"},
{0x0109, "LS_SB_SS_REQUESTOR_ID"},
{0x010A, "LS_SB_SS_CODEWORD"},
{0x010B, "LS_SB_SS_SERVICE_TYPE_ID"},
{0x0130, "LS_SB_LATITUDE_LONGITUDE"},
{0x0131, "LS_SB_ALTITUDE"},
{0x0132, "LS_SB_VELOCITY"},
{0x0133, "LS_SB_NMEA_0183"},
{0x0134, "LS_SB_TIMESTAMP"},
{0x0135, "LS_SB_NMEA_OPTIONS"},
{0x0160, "LS_SB_GPS_EXACT_TIME"},
{0x0161, "LS_SB_GPS_USER_DOPS"},
{0x0162, "LS_SB_GPS_SAT_LIST"},
{0x0163, "LS_SB_GPS_CHANNEL_STATUS"},
{0x0524, "LS_SB_GSM_MULTIPLE_SETS"},
{0x0529, "LS_SB_GSM_MEAS_ERROR_INFO"},
{0x052A, "LS_SB_GSM_POSITIONING_INSTR"},
{0x052B, "LS_SB_GSM_LOCATION_INFO"},
{0x052C, "LS_SB_GSM_GPS_MEAS_INFO"},
{0x052D, "LS_SB_GSM_EXT_REF_ID"},
{0x0530, "LS_SB_GSM_GPS_TIME_ASSIST_MEAS"},
{0x0531, "LS_SB_GSM_REQUIRED_RESPONSE_TIME"},
{0x0551, "LS_SB_SS_CLIENT_EXT_ID"},
{0x0554, "LS_SB_SS_CLIENT_NAME"},
{0x0556, "LS_SB_SS_NOTIFICATION_INFO"},
{0x0689, "LS_SB_LTM_TEST_ABORT"},
{0x070B, "LS_SB_LTM_AI2_CMD_PACKET"},
{0x070C, "LS_SB_LTM_AI2_RSP_PACKET"},
{0x070D, "LS_SB_LTM_DELETE_ASSISTANCE_DATA"},
{0x0800, "LS_SB_SUPL_TIMESTAMP"},
{0x0801, "LS_SB_SUPL_POSITION"},
{0x0802, "LS_SB_SUPL_VELOCITY"},
{0x0803, "LS_SB_SUPL_ALLOWED_CAPABILITIES"},
{0x0804, "LS_SB_SUPL_INFO_SET_CAPABILITIES"},
{0x0805, "LS_SB_SUPL_INFO_AD_REQUEST"},
{0x0806, "LS_SB_SUPL_POS"},
{0x0807, "LS_SB_SUPL_RRLP_LOOPBACK"},
{0x0808, "LS_SB_SUPL_QOP"},
{0x0809, "LS_SB_SUPL_SESSION_POSITION"},
{0x080A, "LS_SB_SUPL_SERVER_METHOD"},
{0x0900, "LS_SB_CLIENT_IDENT"},
{0x0901, "LS_SB_HYBRID_TRACKING_INSTR"},
{0x0902, "LS_SB_NPE_POSITION"},
{0x0903, "LS_SB_NPE_TIME"},
{0x0904, "LS_SB_NPE_VELOCITY"},
{0x0905, "LS_SB_NPE_CHANNELS"},
{0x0906, "LS_SB_NPE_NMEA"},
{0x0907, "LS_SB_CELL_INFO_GSM"},
{0x0908, "LS_SB_CELL_INFO_WCDMA"},
{0x0999, "CLMI_SB_ASTNC_GPS_CURR_NAV_MODEL"},
{0x0A00, "LS_SB_WCDMA_POSITIONING_INSTR"},
{0x0A01, "LS_SB_WCDMA_LOCATION_INFO"},
{0x0A02, "LS_SB_WCDMA_MEAS_ERROR_INFO"},
{0x0A03, "LS_SB_WCDMA_GPS_MEAS_INFO"},
{0x1012, "CLMI_SB_ASTNC_GPS_DGPS_CORRECTIONS"},
{0x1013, "CLMI_SB_ASTNC_GPS_EPHEMERIS"},
{0x1014, "CLMI_SB_ASTNC_GPS_IONOSPHERIC"},
{0x1015, "CLMI_SB_ASTNC_GPS_UTC"},
{0x1016, "CLMI_SB_ASTNC_GPS_ALMANAC"},
{0x1017, "CLMI_SB_ASTNC_GPS_BAD_SATELLITES"},
{0x101B, "CLMI_SB_ASTNC_GPS_ACQUISITION"},
{0x1030, "CLMI_SB_ASTNC_GPS_REF_TIME"},
{0x1031, "CLMI_SB_ASTNC_GPS_REF_TIME_UMTS"},
{0x1032, "CLMI_SB_ASTNC_GPS_REF_TIME_GSM"},
{0x1048, "CLMI_SB_ASTNC_FRAME_TRIGGER_UMTS"},
{0x1049, "CLMI_SB_ASTNC_FRAME_TRIGGER_GSM"},
{0x104A, "CLMI_SB_GPS_TOW_RELATION_UMTS"},
{0x104B, "CLMI_SB_GPS_TOW_RELATION_GSM"},
{0x1100, "LS_SB_SENSOR_REGISTRATION_STATUS"},
{0x1101, "LS_SB_SENSOR_TYPE"},
{0x1102, "LS_SB_SENSOR_ACCELEROMETER_ACTION"},
{0x1200, "LS_SB_SOCKET_ADDR"},
{0x1201, "LS_SB_SOCKET_ADDR_EXT"},
{0x1202, "LS_SB_SOCKET_BEARER_TYPE"},
{0x1203, "LS_SB_SOCKET_IPADDR"},
{0xEFEE, "LS_SB_METHOD_INFORMATION"},
{0xEEEF, "CLMI_SB_GPS_PSEUDORANGE_MEAS"},
{0x0000, NULL}
};
static const value_string isi_location_socket_addr_type[] = {
{0x00, "IPV4"},
{0x01, "IPv6"},
{0x02, "FQDN"},
{0x00, NULL }
};
static const value_string isi_location_gps_power[] = {
{0x00, "GPS_OFF"},
{0x01, "GPS_ON"},
{0x00, NULL }
};
static const value_string isi_location_gps_status[] = {
{0x00, "GPS_STATE_NONE"},
{0x01, "GPS_STATE_SEARCH"},
{0x02, "GPS_STATE_FIX"},
{0x03, "GPS_STATE_SLEEP"},
{0x00, NULL }
};
static const value_string isi_location_bearer_type[] = {
{0x02, "BEARER_GPRS"},
{0x04, "BEARER_WLAN"},
{0x00, NULL }
};
static const value_string isi_location_hybrid_cmd[] = {
{0x00, "MEASUREMENT_START"},
{0x01, "MEASUREMENT_MODIFY"},
{0x02, "MEASUREMENT_STOP"},
{0x00, NULL }
};
static const value_string isi_location_hybrid_report_criteria[] = {
{0x00, "LS_HYBRID_REPORT_AT_ALL_INTERVALS"},
{0x01, "LS_HYBRID_REPORT_ONLY_POSITION_CHANGES"},
{0x00, NULL }
};
static const value_string isi_location_hybrid_cause[] = {
{0x00, "LS_HYBRID_CAUSE_SUCCESS"},
{0x01, "LS_HYBRID_CAUSE_NO_POSITION_YET"},
{0x02, "LS_HYBRID_CAUSE_ERROR_UNSPECIFIED"},
{0x03, "LS_HYBRID_CAUSE_ERROR_NO_METHODS"},
{0x00, NULL }
};
static const value_string isi_location_socket_status[] = {
{0x00, "OK"},
{0x01, "ERROR"},
{0x02, "SERVER_NOT_AUTHENTICATED"},
{0x00, NULL }
};
static dissector_handle_t isi_location_handle;
static void dissect_isi_location(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree);
static gint32 hf_isi_location_cmd = -1;
static gint32 hf_isi_location_sub_pkgs = -1;
static gint32 hf_isi_location_sub_type = -1;
static gint32 hf_isi_location_sub_len = -1;
static gint32 hf_isi_location_gps_power = -1;
static gint32 hf_isi_location_gps_status = -1;
static gint32 hf_isi_location_year = -1;
static gint32 hf_isi_location_month = -1;
static gint32 hf_isi_location_day = -1;
static gint32 hf_isi_location_hour = -1;
static gint32 hf_isi_location_minute = -1;
static gint32 hf_isi_location_second = -1;
static gint32 hf_isi_location_latitude = -1;
static gint32 hf_isi_location_longitude = -1;
static gint32 hf_isi_location_eph = -1;
static gint32 hf_isi_location_altitude = -1;
static gint32 hf_isi_location_epv = -1;
static gint32 hf_isi_location_course = -1;
static gint32 hf_isi_location_epd = -1;
static gint32 hf_isi_location_speed = -1;
static gint32 hf_isi_location_eps = -1;
static gint32 hf_isi_location_climb = -1;
static gint32 hf_isi_location_epc = -1;
static gint32 hf_isi_location_mcc = -1;
static gint32 hf_isi_location_mnc = -1;
static gint32 hf_isi_location_lac = -1;
static gint32 hf_isi_location_cid = -1;
static gint32 hf_isi_location_ucid = -1;
static gint32 hf_isi_location_satellites = -1;
static gint32 hf_isi_location_prn = -1;
static gint32 hf_isi_location_sat_used = -1;
static gint32 hf_isi_location_sat_strength = -1;
static gint32 hf_isi_location_sat_elevation = -1;
static gint32 hf_isi_location_sat_azimuth = -1;
static gint32 hf_isi_location_socket_addr_port = -1;
static gint32 hf_isi_location_socket_addr_type = -1;
static gint32 hf_isi_location_socket_addr_ip_len = -1;
static gint32 hf_isi_location_socket_addr_fqdn_len = -1;
static gint32 hf_isi_location_socket_addr_ipv4 = -1;
static gint32 hf_isi_location_socket_addr_ipv6 = -1;
static gint32 hf_isi_location_socket_addr_fqdn = -1;
static gint32 hf_isi_location_socket_bearer = -1;
static gint32 hf_isi_location_hybrid_cmd = -1;
static gint32 hf_isi_location_hybrid_allowed_methods = -1;
static gint32 hf_isi_location_hybrid_options = -1;
static gint32 hf_isi_location_hybrid_interval = -1;
static gint32 hf_isi_location_hybrid_report_criteria = -1;
static gint32 hf_isi_location_hybrid_acwp_timer = -1;
static gint32 hf_isi_location_hybrid_method_cwp = -1;
static gint32 hf_isi_location_hybrid_method_acwp = -1;
static gint32 hf_isi_location_hybrid_method_gnss = -1;
static gint32 hf_isi_location_hybrid_method_agnss = -1;
static gint32 hf_isi_location_hybrid_option_channel_status = -1;
static gint32 hf_isi_location_hybrid_option_cell_info = -1;
static gint32 hf_isi_location_hybrid_option_nmea_0183 = -1;
static gint32 hf_isi_location_hybrid_client_id = -1;
static gint32 hf_isi_location_hybrid_npe_id = -1;
static gint32 hf_isi_location_cause = -1;
static gint32 hf_isi_location_status = -1;
static gint32 hf_isi_location_status_ok = -1;
static gint32 hf_isi_location_status_complete = -1;
static gint32 hf_isi_location_status_fix = -1;
static gint32 hf_isi_location_status_meas_fix = -1;
static gint32 hf_isi_location_socket_descriptor = -1;
static gint32 hf_isi_location_socket_status = -1;
static gint32 hf_isi_location_socket_error = -1;
static gint32 hf_isi_location_data_len = -1;
static gint32 hf_isi_location_data = -1;
static gint ett_flags_methods = -1;
static gint ett_flags_options = -1;
static gint ett_flags_status = -1;
static dissector_handle_t supl_handle;
static const int *isi_location_hybrid_method_flags[] = {
&hf_isi_location_hybrid_method_cwp,
&hf_isi_location_hybrid_method_acwp,
&hf_isi_location_hybrid_method_gnss,
&hf_isi_location_hybrid_method_agnss,
NULL
};
static const int *isi_location_hybrid_option_flags[] = {
&hf_isi_location_hybrid_option_channel_status,
&hf_isi_location_hybrid_option_cell_info,
&hf_isi_location_hybrid_option_nmea_0183,
NULL
};
static const int *isi_location_hybrid_status_flags[] = {
&hf_isi_location_status_ok,
&hf_isi_location_status_complete,
&hf_isi_location_status_fix,
&hf_isi_location_status_meas_fix,
NULL
};
void proto_reg_handoff_isi_location(void) {
static gboolean initialized=FALSE;
if (!initialized) {
isi_location_handle = create_dissector_handle(dissect_isi_location, proto_isi);
dissector_add_uint("isi.resource", 0x54, isi_location_handle);
supl_handle = find_dissector("ulp");
}
}
void proto_register_isi_location(void) {
static hf_register_info hf[] = {
{ &hf_isi_location_cmd,
{ "Command", "isi.location.cmd", FT_UINT8, BASE_HEX, isi_location_id, 0x0, "Command", HFILL }},
{ &hf_isi_location_sub_pkgs,
{ "Number of Subpackets", "isi.location.pkgs", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Subpackets", HFILL }},
{ &hf_isi_location_sub_type,
{ "Subpacket Type", "isi.location.sub.type", FT_UINT16, BASE_HEX, isi_location_sub_id, 0x0, "Subpacket Type", HFILL }},
{ &hf_isi_location_sub_len,
{ "Subpacket Length", "isi.location.sub.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Subpacket Length", HFILL }},
{ &hf_isi_location_gps_power,
{ "Power", "isi.location.power", FT_UINT8, BASE_HEX, isi_location_gps_power, 0x0, "Power", HFILL }},
{ &hf_isi_location_gps_status,
{ "Status", "isi.location.status", FT_UINT8, BASE_HEX, isi_location_gps_status, 0x0, "Status", HFILL }},
{ &hf_isi_location_year,
{ "Year", "isi.location.date.year", FT_UINT16, BASE_DEC, NULL, 0x0, "Year", HFILL }},
{ &hf_isi_location_month,
{ "Month", "isi.location.date.month", FT_UINT8, BASE_DEC, NULL, 0x0, "Month", HFILL }},
{ &hf_isi_location_day,
{ "Day", "isi.location.date.day", FT_UINT8, BASE_DEC, NULL, 0x0, "Day", HFILL }},
{ &hf_isi_location_hour,
{ "Hour", "isi.location.time.hour", FT_UINT8, BASE_DEC, NULL, 0x0, "Hour", HFILL }},
{ &hf_isi_location_minute,
{ "Minute", "isi.location.time.minute", FT_UINT8, BASE_DEC, NULL, 0x0, "Minute", HFILL }},
{ &hf_isi_location_second,
{ "Second", "isi.location.time.second", FT_FLOAT, BASE_NONE, NULL, 0x0, "Second", HFILL }},
{ &hf_isi_location_latitude,
{ "Latitude", "isi.location.lat", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Latitude", HFILL }},
{ &hf_isi_location_longitude,
{ "Longitude", "isi.location.lon", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Longitude", HFILL }},
{ &hf_isi_location_eph,
{ "Position Accuracy", "isi.location.eph", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPH (position accuracy) in meter", HFILL }},
{ &hf_isi_location_altitude,
{ "Altitude", "isi.location.alt", FT_INT16, BASE_DEC, NULL, 0x0, "Altitude in meter", HFILL }},
{ &hf_isi_location_epv,
{ "Altitude Accuracy", "isi.location.epv", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPV (altitude accuracy) in meter", HFILL }},
{ &hf_isi_location_course,
{ "Course", "isi.location.course", FT_FLOAT, BASE_NONE, NULL, 0x0, "Course in degree", HFILL }},
{ &hf_isi_location_epd,
{ "Course Accuracy", "isi.location.epd", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPD (course accuracy) in degree", HFILL }},
{ &hf_isi_location_speed,
{ "Speed", "isi.location.speed", FT_FLOAT, BASE_NONE, NULL, 0x0, "Speed in km/h", HFILL }},
{ &hf_isi_location_eps,
{ "Speed Accuracy", "isi.location.eps", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPS (speed accuracy) in km/h", HFILL }},
{ &hf_isi_location_climb,
{ "Climb", "isi.location.climb", FT_FLOAT, BASE_NONE, NULL, 0x0, "Climb in km/h", HFILL }},
{ &hf_isi_location_satellites,
{ "Visible Satellites", "isi.location.satellites", FT_UINT8, BASE_DEC, NULL, 0x0, "Visible Satellites", HFILL }},
{ &hf_isi_location_prn,
{ "Pseudeorandom Noise (PRN)", "isi.location.sat.prn", FT_UINT8, BASE_HEX_DEC, NULL, 0x0, "Pseudeorandom Noise (PRN)", HFILL }},
{ &hf_isi_location_sat_used,
{ "in use", "isi.location.sat.used", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "in use", HFILL }},
{ &hf_isi_location_sat_strength,
{ "Signal Strength", "isi.location.sat.strength", FT_FLOAT, BASE_NONE, NULL, 0x0, "Signal Strength", HFILL }},
{ &hf_isi_location_sat_elevation,
{ "Elevation", "isi.location.sat.elevation", FT_FLOAT, BASE_NONE, NULL, 0x0, "Elevation", HFILL }},
{ &hf_isi_location_sat_azimuth,
{ "Azimuth", "isi.location.sat.azimuth", FT_FLOAT, BASE_NONE, NULL, 0x0, "Azimuth", HFILL }},
{ &hf_isi_location_epc,
{ "Climb Accuracy", "isi.location.epc", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPC (climb accuracy) in km/h", HFILL }},
{ &hf_isi_location_mcc,
{ "Mobile Country Code (MCC)", "isi.location.gsm.mcc", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Mobile Country Code (MCC)", HFILL }},
{ &hf_isi_location_mnc,
{ "Mobile Network Code (MNC)", "isi.location.gsm.mnc", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Mobile Network Code (MNC)", HFILL }},
{ &hf_isi_location_lac,
{ "Location Area Code (LAC)", "isi.location.gsm.lac", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Location Area Code (LAC)", HFILL }},
{ &hf_isi_location_cid,
{ "Cell ID (CID)", "isi.location.gsm.cid", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Cell ID (CID)", HFILL }},
{ &hf_isi_location_ucid,
{ "Cell ID (UCID)", "isi.location.gsm.ucid", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, "Cell ID (UCID)", HFILL }},
{ &hf_isi_location_socket_addr_port,
{ "Port", "isi.location.socket.addr.port", FT_UINT16, BASE_DEC, NULL, 0x0, "Port", HFILL }},
{ &hf_isi_location_socket_addr_type,
{ "Type", "isi.location.socket.addr.type", FT_UINT8, BASE_HEX, isi_location_socket_addr_type, 0x0, "Type", HFILL }},
{ &hf_isi_location_socket_addr_ip_len,
{ "IP Length", "isi.location.socket.addr.ip.len", FT_UINT8, BASE_DEC, NULL, 0x0, "IP Length", HFILL }},
{ &hf_isi_location_socket_addr_fqdn_len,
{ "Domain Length", "isi.location.socket.addr.fqdn.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Domain Length", HFILL }},
{ &hf_isi_location_socket_addr_ipv4,
{ "IPv4", "isi.location.socket.addr.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IPv6", HFILL }},
{ &hf_isi_location_socket_addr_ipv6,
{ "IPv6", "isi.location.socket.addr.ip", FT_IPv6, BASE_NONE, NULL, 0x0, "IPv6", HFILL }},
{ &hf_isi_location_socket_addr_fqdn,
{ "Domain", "isi.location.socket.addr.fqdn", FT_STRING, BASE_NONE, NULL, 0x0, "Domain", HFILL }},
{ &hf_isi_location_socket_bearer,
{ "Bearer Type", "isi.location.bearer", FT_UINT8, BASE_HEX, isi_location_bearer_type, 0x0, "Bearer Type", HFILL }},
{ &hf_isi_location_hybrid_cmd,
{ "Hybrid Command", "isi.location.hybrid.cmd", FT_UINT8, BASE_HEX, isi_location_hybrid_cmd, 0x0, "Hybrid Command", HFILL }},
{ &hf_isi_location_hybrid_allowed_methods,
{ "Allowed Methods", "isi.location.hybrid.allowed_methods", FT_UINT32, BASE_HEX, NULL, 0x0, "Allowed Methods", HFILL }},
{ &hf_isi_location_hybrid_options,
{ "Options", "isi.location.hybrid.options", FT_UINT32, BASE_HEX, NULL, 0x0, "Options", HFILL }},
{ &hf_isi_location_hybrid_interval,
{ "Interval", "isi.location.hybrid.interval", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, "Interval", HFILL }},
{ &hf_isi_location_hybrid_report_criteria,
{ "Report Criteria", "isi.location.hybrid.report_criteria", FT_UINT8, BASE_HEX, isi_location_hybrid_report_criteria, 0x0, "Report Criteria", HFILL }},
{ &hf_isi_location_hybrid_acwp_timer,
{ "ACWP Timer", "isi.location.hybrid.acwp_timer", FT_UINT8, BASE_DEC, NULL, 0x0, "ACWP Timer", HFILL }},
{ &hf_isi_location_hybrid_option_channel_status,
{ "Channel Status", "isi.location.hybrid.options.channel_status", FT_BOOLEAN, BASE_NONE, NULL, 0x000000001, "Channel Status", HFILL }},
{ &hf_isi_location_hybrid_option_cell_info,
{ "Cell Info", "isi.location.hybrid.options.cell_info", FT_BOOLEAN, BASE_NONE, NULL, 0x000000002, "Cell Info", HFILL }},
{ &hf_isi_location_hybrid_option_nmea_0183,
{ "NMEA 0183", "isi.location.hybrid.options.nmea_0183", FT_BOOLEAN, BASE_NONE, NULL, 0x000000004, "NMEA 0183", HFILL }},
{ &hf_isi_location_hybrid_method_cwp,
{ "CWP", "isi.location.hybrid.methods.cwp", FT_BOOLEAN, BASE_NONE, NULL, 0x000000001, "CWP", HFILL }},
{ &hf_isi_location_hybrid_method_acwp,
{ "ACWP", "isi.location.hybrid.methods.acwp", FT_BOOLEAN, BASE_NONE, NULL, 0x000000002, "ACWP", HFILL }},
{ &hf_isi_location_hybrid_method_gnss,
{ "GNSS", "isi.location.hybrid.methods.gnss", FT_BOOLEAN, BASE_NONE, NULL, 0x000000004, "GNSS", HFILL }},
{ &hf_isi_location_hybrid_method_agnss,
{ "AGNSS", "isi.location.hybrid.methods.agnss", FT_BOOLEAN, BASE_NONE, NULL, 0x000000008, "AGNSS", HFILL }},
{ &hf_isi_location_hybrid_client_id,
{ "Client ID", "isi.location.hybrid.client_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Client ID", HFILL }},
{ &hf_isi_location_hybrid_npe_id,
{ "NPE ID", "isi.location.hybrid.npe_id", FT_UINT32, BASE_HEX, NULL, 0x0, "NPE ID", HFILL }},
{ &hf_isi_location_cause,
{ "Cause", "isi.location.hybrid.cause", FT_UINT8, BASE_HEX, isi_location_hybrid_cause, 0x0, "Cause", HFILL }},
{ &hf_isi_location_status,
{ "Status", "isi.location.status", FT_UINT8, BASE_HEX, NULL, 0x0, "Status", HFILL }},
{ &hf_isi_location_status_ok,
{ "OK", "isi.location.status.ok", FT_BOOLEAN, BASE_NONE, NULL, 0x01, "OK", HFILL }},
{ &hf_isi_location_status_complete,
{ "Complete", "isi.location.status.complete", FT_BOOLEAN, BASE_NONE, NULL, 0x20, "Complete", HFILL }},
{ &hf_isi_location_status_fix,
{ "Fix", "isi.location.status.fix", FT_BOOLEAN, BASE_NONE, NULL, 0x40, "Fix", HFILL }},
{ &hf_isi_location_status_meas_fix,
{ "Measure Fix", "isi.location.status.meas_fix", FT_BOOLEAN, BASE_NONE, NULL, 0x80, "Measure Fix", HFILL }},
{ &hf_isi_location_socket_descriptor,
{ "Descriptor", "isi.location.socket.status", FT_UINT8, BASE_HEX, NULL, 0x0, "Descriptor", HFILL }},
{ &hf_isi_location_socket_status,
{ "Status", "isi.location.socket.status", FT_UINT8, BASE_HEX, isi_location_socket_status, 0x0, "Status", HFILL }},
{ &hf_isi_location_socket_error,
{ "Error Number", "isi.location.socket.error", FT_UINT16, BASE_HEX, NULL, 0x0, "Error Number", HFILL }},
{ &hf_isi_location_data_len,
{ "Data Length", "isi.location.data.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Data Length", HFILL }},
{ &hf_isi_location_data,
{ "Data", "isi.location.data", FT_BYTES, BASE_NONE, NULL, 0x0, "Data Length", HFILL }}
};
static gint *ett[] = {
&ett_flags_status,
&ett_flags_methods,
&ett_flags_options
};
proto_register_field_array(proto_isi, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("isi.location", dissect_isi_location, proto_isi);
}
static size_t dissect_isi_location_subpkg(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, proto_tree *tree, size_t offset) {
guint16 sptype = tvb_get_ntohs(tvb, offset+0);
guint16 splen = tvb_get_ntohs(tvb, offset+2);
proto_item *subitem;
proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, offset, splen, ett_isi_msg, &subitem, "Subpacket (%s)", val_to_str(sptype, isi_location_sub_id, "unknown: 0x%x"));
proto_tree_add_item(subtree, hf_isi_location_sub_type, tvb, offset+0, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_sub_len, tvb, offset+2, 2, FALSE);
offset += 4;
switch(sptype) {
case 0x1200: ; /* LS_SB_SOCKET_ADDR */
proto_tree_add_item(subtree, hf_isi_location_socket_addr_port, tvb, offset+0, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_socket_addr_type, tvb, offset+2, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_socket_addr_ip_len, tvb, offset+3, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_socket_addr_fqdn_len, tvb, offset+4, 1, FALSE);
guint8 type = tvb_get_guint8(tvb, offset+2);
guint8 ip_len = tvb_get_guint8(tvb, offset+3);
guint8 fqdn_len = tvb_get_guint8(tvb, offset+4);
if(type == 0x00 && ip_len >= FT_IPv4_LEN)
proto_tree_add_item(subtree, hf_isi_location_socket_addr_ipv4, tvb, offset+8, ip_len, FALSE);
if(type == 0x01 && ip_len >= FT_IPv6_LEN)
proto_tree_add_item(subtree, hf_isi_location_socket_addr_ipv6, tvb, offset+8, ip_len, FALSE);
if(type == 0x02)
proto_tree_add_item(subtree, hf_isi_location_socket_addr_fqdn, tvb, offset+8+ip_len, fqdn_len, FALSE);
break;
case 0x1202: ; /* LS_SB_SOCKET_BEARER_TYPE */
proto_tree_add_item(subtree, hf_isi_location_socket_bearer, tvb, offset+0, 1, FALSE);
break;
case 0x0901: ; /* LS_SB_HYBRID_TRACKING_INSTR */
proto_tree_add_bitmask(subtree, tvb, offset+0, hf_isi_location_hybrid_allowed_methods, ett_flags_methods, isi_location_hybrid_method_flags, ENC_BIG_ENDIAN);
proto_tree_add_bitmask(subtree, tvb, offset+4, hf_isi_location_hybrid_options, ett_flags_options, isi_location_hybrid_option_flags, ENC_BIG_ENDIAN);
guint16 time_raw = tvb_get_ntohs(tvb, offset+8);
nstime_t time_conv;
time_conv.nsecs = (time_raw % 10) * 100000;
time_conv.secs = time_raw / 10;
proto_tree_add_time(subtree, hf_isi_location_hybrid_interval, tvb, offset+8, 2, &time_conv);
proto_tree_add_item(subtree, hf_isi_location_hybrid_report_criteria, tvb, offset+10, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_hybrid_acwp_timer, tvb, offset+11, 1, FALSE);
break;
case 0x0902: ; /* LS_SB_NPE_POSITION */
double lat = tvb_get_ntohl(tvb, offset+0);
lat = (lat*360)/4294967296;
if(lat > 180.0) lat -= 360.0;
proto_tree_add_double(subtree, hf_isi_location_latitude, tvb, offset+0, 4, lat);
double lon = tvb_get_ntohl(tvb, offset+4);
lon = (lon*360)/4294967296;
if(lon > 180.0) lon -= 360.0;
proto_tree_add_double(subtree, hf_isi_location_longitude, tvb, offset+4, 4, lon);
float eph = tvb_get_ntohl(tvb, offset+12) / 100.0;
proto_tree_add_float(subtree, hf_isi_location_eph, tvb, offset+12, 4, eph);
gint32 altitude = (tvb_get_ntohs(tvb, offset+18) - tvb_get_ntohs(tvb, offset+22))/2;
proto_tree_add_int(subtree, hf_isi_location_altitude, tvb, offset+18, 6, altitude);
float epv = tvb_get_ntohs(tvb, offset+20) / 2;
proto_tree_add_float(subtree, hf_isi_location_epv, tvb, offset+20, 2, epv);
break;
case 0x0903: ; /* LS_SB_NPE_TIME */
proto_tree_add_item(subtree, hf_isi_location_year, tvb, offset+0, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_month, tvb, offset+2, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_day, tvb, offset+3, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_hour, tvb, offset+5, 1, FALSE);
proto_tree_add_item(subtree, hf_isi_location_minute, tvb, offset+6, 1, FALSE);
float second = tvb_get_ntohs(tvb, offset+8) / 1000.0;
proto_tree_add_float(subtree, hf_isi_location_second, tvb, offset+8, 2, second);
break;
case 0x0904: ; /* LS_SB_NPE_VELOCITY */
float course = tvb_get_ntohs(tvb, offset+0) / 100.0;
proto_tree_add_float(subtree, hf_isi_location_course, tvb, offset+0, 2, course);
float epd = tvb_get_ntohs(tvb, offset+2) / 100.0;
proto_tree_add_float(subtree, hf_isi_location_epd, tvb, offset+2, 2, epd);
float speed = tvb_get_ntohs(tvb, offset+6) * CMS_TO_KMH;
proto_tree_add_float(subtree, hf_isi_location_speed, tvb, offset+6, 2, speed);
float eps = tvb_get_ntohs(tvb, offset+8) * CMS_TO_KMH;
proto_tree_add_float(subtree, hf_isi_location_eps, tvb, offset+8, 2, eps);
float climb = tvb_get_ntohs(tvb, offset+10) * CMS_TO_KMH;
proto_tree_add_float(subtree, hf_isi_location_climb, tvb, offset+10, 2, climb);
float epc = tvb_get_ntohs(tvb, offset+12) * CMS_TO_KMH;
proto_tree_add_float(subtree, hf_isi_location_epc, tvb, offset+12, 2, epc);
break;
case 0x0905: ; /* LS_SB_NPE_CHANNELS */
guint8 satellites = tvb_get_guint8(tvb, offset+0);
proto_tree_add_item(subtree, hf_isi_location_satellites, tvb, offset+0, 1, FALSE);
int sat;
for(sat = 0; sat < satellites ; sat++) {
int pos = offset+4+(sat*SAT_PKG_LEN);
proto_tree *sattree = proto_tree_add_subtree_format(subtree, tvb, offset, splen, ett_isi_msg, NULL, "Satellite %d", sat);
float signal_strength = tvb_get_ntohs(tvb, pos+3) / 100.0;
float elevation = tvb_get_ntohs(tvb, pos+6) / 100.0;
float azimuth = tvb_get_ntohs(tvb, pos+8) / 100.0;
proto_tree_add_item(sattree, hf_isi_location_prn, tvb, pos+1, 1, FALSE);
proto_tree_add_item(sattree, hf_isi_location_sat_used, tvb, pos+2, 1, FALSE);
proto_tree_add_float(sattree, hf_isi_location_sat_strength, tvb, pos+3, 2, signal_strength);
proto_tree_add_float(sattree, hf_isi_location_sat_elevation, tvb, pos+6, 2, elevation);
proto_tree_add_float(sattree, hf_isi_location_sat_azimuth, tvb, pos+8, 2, azimuth);
}
break;
case 0x0907: /* LS_SB_CELL_INFO_GSM */
proto_tree_add_item(subtree, hf_isi_location_mcc, tvb, offset+0, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_mnc, tvb, offset+2, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_lac, tvb, offset+4, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_cid, tvb, offset+6, 2, FALSE);
break;
case 0x0908: /* LS_SB_CELL_INFO_WCDMA */
proto_tree_add_item(subtree, hf_isi_location_mcc, tvb, offset+0, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_mnc, tvb, offset+2, 2, FALSE);
proto_tree_add_item(subtree, hf_isi_location_ucid, tvb, offset+4, 4, FALSE);
break;
default:
expert_add_info_format(pinfo, subitem, &ei_isi_unsupported_packet, "unsupported sub-packet");
break;
}
return splen;
}
static void dissect_isi_location(tvbuff_t *tvb, packet_info *pinfo, proto_item *isitree) {
proto_item *item = NULL;
proto_tree *tree = NULL;
guint8 cmd, pkgcount;
guint16 data_len;
size_t offset;
int i;
if(isitree) {
tree = proto_tree_add_subtree_format(isitree, tvb, 0, -1, ett_isi_msg, &item, "Payload");
proto_tree_add_item(tree, hf_isi_location_cmd, tvb, 0, 1, FALSE);
cmd = tvb_get_guint8(tvb, 0);
switch(cmd) {
case 0x7D: /* LS_GPS_STATUS_IND */
proto_tree_add_item(tree, hf_isi_location_gps_power, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_gps_status, tvb, 2, 1, FALSE);
guint8 status = tvb_get_guint8(tvb, 2);
col_add_fstr(pinfo->cinfo, COL_INFO, "GPS Status Indication: %s", val_to_str(status, isi_location_gps_status, "unknown (0x%x)"));
break;
case 0x84: /* LS_SOCKET_OPEN_REQUEST_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Open Request");
pkgcount = tvb_get_guint8(tvb, 1);
proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 1, 1, FALSE);
offset = 0x03;
for(i=0; i<pkgcount; i++) {
offset += dissect_isi_location_subpkg(tvb, pinfo, item, tree, offset);
}
break;
case 0x85: /* LS_SOCKET_OPEN_RESPONSE_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Open Response");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE);
pkgcount = tvb_get_guint8(tvb, 3);
proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 3, 1, FALSE);
offset = 0x07;
for(i=0; i<pkgcount; i++) {
offset += dissect_isi_location_subpkg(tvb, pinfo, item, tree, offset);
}
break;
case 0x86: /* LS_SOCKET_SEND_REQUEST_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Send Request");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_data_len, tvb, 3, 2, FALSE);
data_len = tvb_get_ntohs(tvb, 3);
if(supl_handle == NULL) {
proto_tree_add_item(tree, hf_isi_location_data, tvb, 7, data_len, FALSE);
} else {
tvbuff_t *data_tvb = tvb_new_subset(tvb, 7, data_len, data_len);
call_dissector(supl_handle, data_tvb, pinfo, tree);
}
break;
case 0x87: /* LS_SOCKET_SEND_RESPONSE_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Send Response");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_socket_error, tvb, 3, 2, FALSE);
break;
case 0x88: /* LS_SOCKET_RECV_REQ */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Receive Request");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_data_len, tvb, 3, 2, FALSE);
data_len = tvb_get_ntohs(tvb, 3);
if(supl_handle == NULL) {
proto_tree_add_item(tree, hf_isi_location_data, tvb, 7, data_len, FALSE);
} else {
tvbuff_t *data_tvb = tvb_new_subset(tvb, 7, data_len, data_len);
call_dissector(supl_handle, data_tvb, pinfo, tree);
}
break;
case 0x89: /* LS_SOCKET_RECV_RESP */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Receive Response");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
break;
case 0x8a: /* LS_SOCKET_CLOSE_REQUEST_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Close Request");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
break;
case 0x8b: /* LS_SOCKET_CLOSE_RESPONSE_NTF */
col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Close Response");
proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE);
break;
case 0x90: /* LS_HYBRID_TRACKING_REQ */
col_set_str(pinfo->cinfo, COL_INFO, "Hybrid Tracking Request");
proto_tree_add_item(tree, hf_isi_location_hybrid_cmd, tvb, 1, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 2, 1, FALSE);
pkgcount = tvb_get_guint8(tvb, 2);
proto_tree_add_item(tree, hf_isi_location_hybrid_client_id, tvb, 3, 4, FALSE);
proto_tree_add_item(tree, hf_isi_location_hybrid_npe_id, tvb, 7, 4, FALSE);
offset = 0x0b;
for(i=0; i<pkgcount; i++) {
offset += dissect_isi_location_subpkg(tvb, pinfo, item, tree, offset);
}
break;
case 0x91: /* LS_HYBRID_TRACKING_RESP */
col_set_str(pinfo->cinfo, COL_INFO, "Hybrid Tracking Response");
proto_tree_add_bitmask(tree, tvb, 1, hf_isi_location_status, ett_flags_status, isi_location_hybrid_status_flags, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_isi_location_cause, tvb, 2, 1, FALSE);
proto_tree_add_item(tree, hf_isi_location_hybrid_client_id, tvb, 3, 4, FALSE);
proto_tree_add_item(tree, hf_isi_location_hybrid_npe_id, tvb, 7, 4, FALSE);
break;
case 0x92: /* LS_HYBRID_TRACKING_NTF */
col_set_str(pinfo->cinfo, COL_INFO, "Hybrid Tracking Notification");
pkgcount = tvb_get_guint8(tvb, 0x07);
proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 0x07, 1, FALSE);
offset = 0x0b;
for(i=0; i<pkgcount; i++) {
offset += dissect_isi_location_subpkg(tvb, pinfo, item, tree, offset);
}
break;
case 0xF0: /* COMMON_MESSAGE */
dissect_isi_common("GPS", tvb, pinfo, tree);
break;
default:
expert_add_info_format(pinfo, item, &ei_isi_unsupported_packet, "unsupported location packet");
break;
}
}
}