forked from osmocom/wireshark
![Dario Lombardo](/assets/img/avatar_default.png)
Change-Id: I96e1f1cdbaaf49d65705ecacc903f73cf0e47d7c Reviewed-on: https://code.wireshark.org/review/26334 Petri-Dish: Dario Lombardo <lomato@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Jaap Keuter <jaap.keuter@xs4all.nl>
2218 lines
78 KiB
C
2218 lines
78 KiB
C
/* packet-hartip.c
|
|
* Routines for HART-IP packet dissection
|
|
* Copyright 2012, Bill Schiller <bill.schiller@emerson.com>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* Copied from packet-mbtcp.c
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/stats_tree.h>
|
|
#include <epan/expert.h>
|
|
#include <epan/prefs.h>
|
|
#include "packet-tcp.h"
|
|
|
|
void proto_register_hartip(void);
|
|
void proto_reg_handoff_hartip(void);
|
|
|
|
static dissector_handle_t hartip_tcp_handle;
|
|
static dissector_handle_t hartip_udp_handle;
|
|
|
|
static gboolean hartip_desegment = TRUE;
|
|
|
|
static int proto_hartip = -1;
|
|
static int hf_hartip_hdr_version = -1;
|
|
static int hf_hartip_hdr_message_id = -1;
|
|
static int hf_hartip_hdr_message_type = -1;
|
|
static int hf_hartip_hdr_status = -1;
|
|
static int hf_hartip_hdr_transaction_id = -1;
|
|
static int hf_hartip_hdr_msg_length = -1;
|
|
|
|
static int hf_hartip_data = -1;
|
|
static int hf_hartip_master_type = -1;
|
|
static int hf_hartip_inactivity_close_timer = -1;
|
|
static int hf_hartip_error_code = -1;
|
|
|
|
static int hf_hartip_pt_preambles = -1;
|
|
static int hf_hartip_pt_delimiter = -1;
|
|
static int hf_hartip_pt_short_addr = -1;
|
|
static int hf_hartip_pt_long_addr = -1;
|
|
static int hf_hartip_pt_command = -1;
|
|
static int hf_hartip_pt_length = -1;
|
|
static int hf_hartip_pt_response_code = -1;
|
|
static int hf_hartip_pt_device_status = -1;
|
|
static int hf_hartip_pt_payload = -1;
|
|
static int hf_hartip_pt_checksum = -1;
|
|
|
|
static gint ett_hartip = -1;
|
|
static gint ett_hartip_hdr = -1;
|
|
static gint ett_hartip_body = -1;
|
|
|
|
static expert_field ei_hartip_data_none = EI_INIT;
|
|
static expert_field ei_hartip_data_unexpected = EI_INIT;
|
|
|
|
/* Command 0 response */
|
|
static int hf_hartip_pt_rsp_expansion_code = -1;
|
|
static int hf_hartip_pt_rsp_expanded_device_type = -1;
|
|
static int hf_hartip_pt_rsp_req_min_preambles = -1;
|
|
static int hf_hartip_pt_rsp_hart_protocol_major_rev = -1;
|
|
static int hf_hartip_pt_rsp_device_rev = -1;
|
|
static int hf_hartip_pt_rsp_software_rev = -1;
|
|
static int hf_hartip_pt_rsp_hardware_rev_physical_signal = -1;
|
|
static int hf_hartip_pt_rsp_flage = -1;
|
|
static int hf_hartip_pt_rsp_device_id = -1;
|
|
static int hf_hartip_pt_rsp_rsp_min_preambles = -1;
|
|
static int hf_hartip_pt_rsp_max_device_variables = -1;
|
|
static int hf_hartip_pt_rsp_configuration_change_counter = -1;
|
|
static int hf_hartip_pt_rsp_extended_device_status = -1;
|
|
static int hf_hartip_pt_rsp_manufacturer_Identification_code = -1;
|
|
static int hf_hartip_pt_rsp_private_label = -1;
|
|
static int hf_hartip_pt_rsp_device_profile = -1;
|
|
|
|
/* Command 2 response */
|
|
static int hf_hartip_pt_rsp_pv_percent_range = -1;
|
|
|
|
/* Command 3 response */
|
|
static int hf_hartip_pt_rsp_pv_loop_current = -1;
|
|
static int hf_hartip_pt_rsp_pv_units = -1;
|
|
static int hf_hartip_pt_rsp_pv = -1;
|
|
static int hf_hartip_pt_rsp_sv_units = -1;
|
|
static int hf_hartip_pt_rsp_sv = -1;
|
|
static int hf_hartip_pt_rsp_tv_units = -1;
|
|
static int hf_hartip_pt_rsp_tv = -1;
|
|
static int hf_hartip_pt_rsp_qv_units = -1;
|
|
static int hf_hartip_pt_rsp_qv = -1;
|
|
|
|
/* Command 7 response*/
|
|
static int hf_hartip_pt_rsp_loop_current_mode = -1;
|
|
|
|
/* Command 8 response*/
|
|
static int hf_hartip_pt_rsp_primary_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_secondary_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_tertiary_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_quaternary_var_classify = -1;
|
|
|
|
/* Command 9 response */
|
|
static int hf_hartip_pt_rsp_slot0_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot0_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot0_units = -1;
|
|
static int hf_hartip_pt_rsp_slot0_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot0_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot1_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot1_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot1_units = -1;
|
|
static int hf_hartip_pt_rsp_slot1_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot1_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot2_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot2_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot2_units = -1;
|
|
static int hf_hartip_pt_rsp_slot2_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot2_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot3_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot3_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot3_units = -1;
|
|
static int hf_hartip_pt_rsp_slot3_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot3_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot4_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot4_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot4_units = -1;
|
|
static int hf_hartip_pt_rsp_slot4_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot4_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot5_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot5_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot5_units = -1;
|
|
static int hf_hartip_pt_rsp_slot5_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot5_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot6_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot6_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot6_units = -1;
|
|
static int hf_hartip_pt_rsp_slot6_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot6_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot7_device_var = -1;
|
|
static int hf_hartip_pt_rsp_slot7_device_var_classify = -1;
|
|
static int hf_hartip_pt_rsp_slot7_units = -1;
|
|
static int hf_hartip_pt_rsp_slot7_device_var_value = -1;
|
|
static int hf_hartip_pt_rsp_slot7_device_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot0_timestamp = -1;
|
|
|
|
/* Command 13 response */
|
|
static int hf_hartip_pt_rsp_packed_descriptor = -1;
|
|
static int hf_hartip_pt_rsp_day = -1;
|
|
static int hf_hartip_pt_rsp_month = -1;
|
|
static int hf_hartip_pt_rsp_year = -1;
|
|
|
|
/* Command 14 response */
|
|
static int hf_hartip_pt_rsp_transducer_serial_number = -1;
|
|
static int hf_hartip_pt_rsp_transducer_limit_min_span_units = -1;
|
|
static int hf_hartip_pt_rsp_upper_transducer_limit = -1;
|
|
static int hf_hartip_pt_rsp_lower_transducer_limit = -1;
|
|
static int hf_hartip_pt_rsp_minimum_span = -1;
|
|
|
|
/* Command 15 response */
|
|
static int hf_hartip_pt_rsp_pv_alarm_selection_code = -1;
|
|
static int hf_hartip_pt_rsp_pv_transfer_function_code = -1;
|
|
static int hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units = -1;
|
|
static int hf_hartip_pt_rsp_pv_upper_range_value = -1;
|
|
static int hf_hartip_pt_rsp_pv_lower_range_value = -1;
|
|
static int hf_hartip_pt_rsp_pv_damping_value = -1;
|
|
static int hf_hartip_pt_rsp_write_protect_code = -1;
|
|
static int hf_hartip_pt_rsp_reserved = -1;
|
|
static int hf_hartip_pt_rsp_pv_analog_channel_flags = -1;
|
|
|
|
/* Command 16 and 19 response */
|
|
static int hf_hartip_pt_rsp_final_assembly_number = -1;
|
|
|
|
/* response Tag */
|
|
static int hf_hartip_pt_rsp_tag = -1;
|
|
|
|
/* response Message */
|
|
static int hf_hartip_pt_rsp_message = -1;
|
|
|
|
/* Command 48 response */
|
|
static int hf_hartip_pt_rsp_device_sp_status = -1;
|
|
static int hf_hartip_pt_rsp_device_op_mode = -1;
|
|
static int hf_hartip_pt_rsp_standardized_status_0 = -1;
|
|
static int hf_hartip_pt_rsp_standardized_status_1 = -1;
|
|
static int hf_hartip_pt_rsp_analog_channel_saturated = -1;
|
|
static int hf_hartip_pt_rsp_standardized_status_2 = -1;
|
|
static int hf_hartip_pt_rsp_standardized_status_3 = -1;
|
|
static int hf_hartip_pt_rsp_analog_channel_fixed = -1;
|
|
|
|
/* Command 77 response */
|
|
static int hf_hartip_pt_rsp_io_card = -1;
|
|
static int hf_hartip_pt_rsp_channel = -1;
|
|
static int hf_hartip_pt_rsp_embedded_cmd_delimiter = -1;
|
|
static int hf_hartip_pt_rsp_poll_address = -1;
|
|
static int hf_hartip_pt_rsp_embedded_cmd = -1;
|
|
|
|
/* Command 31 and 178 response */
|
|
static int hf_hartip_pt_rsp_number_of_commands = -1;
|
|
static int hf_hartip_pt_rsp_command_number = -1;
|
|
static int hf_hartip_pt_rsp_command_byte_count = -1;
|
|
|
|
/* Command 31, 77 and 178 response */
|
|
static int hf_hartip_pt_rsp_data = -1;
|
|
|
|
/*Command 203 response*/
|
|
static int hf_hartip_pt_rsp_index_of_first_discrete_var = -1;
|
|
static int hf_hartip_pt_rsp_number_of_discrete_vars = -1;
|
|
static int hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot0_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot0_discrete_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot1_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot1_discrete_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot2_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot2_discrete_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot3_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot3_discrete_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot4_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot4_discrete_var_status = -1;
|
|
|
|
static int hf_hartip_pt_rsp_slot5_discrete_var_state = -1;
|
|
static int hf_hartip_pt_rsp_slot5_discrete_var_status = -1;
|
|
|
|
#define HARTIP_HEADER_LENGTH 8
|
|
#define HARTIP_PORT 5094
|
|
|
|
/* HARTIP header */
|
|
typedef struct _hartip_hdr {
|
|
guint8 version;
|
|
guint8 message_type;
|
|
guint8 message_id;
|
|
guint8 status;
|
|
guint16 transaction_id;
|
|
guint16 length;
|
|
} hartip_hdr;
|
|
|
|
/* Message IDs */
|
|
#define SESSION_INITIATE_ID 0
|
|
#define SESSION_CLOSE_ID 1
|
|
#define KEEP_ALIVE_ID 2
|
|
#define PASS_THROUGH_ID 3
|
|
|
|
/* Message types */
|
|
#define REQUEST_MSG_TYPE 0
|
|
#define RESPONSE_MSG_TYPE 1
|
|
#define PUBLISH_MSG_TYPE 2
|
|
#define ERROR_MSG_TYPE 3
|
|
#define NAK_MSG_TYPE 15
|
|
|
|
static const value_string hartip_message_id_values[] = {
|
|
{ SESSION_INITIATE_ID, "Session Initiate" },
|
|
{ SESSION_CLOSE_ID, "Session Close" },
|
|
{ KEEP_ALIVE_ID, "Keep Alive" },
|
|
{ PASS_THROUGH_ID, "Pass Through" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string hartip_message_type_values[] = {
|
|
{ REQUEST_MSG_TYPE, "Request" },
|
|
{ RESPONSE_MSG_TYPE, "Response" },
|
|
{ PUBLISH_MSG_TYPE, "Publish" },
|
|
{ ERROR_MSG_TYPE, "Error" },
|
|
{ NAK_MSG_TYPE, "Error" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* Host types */
|
|
#define SECONDARY_MASTER_TYPE 0
|
|
#define PRIMARY_MASTER_TYPE 1
|
|
|
|
static const value_string hartip_master_type_values[] = {
|
|
{ SECONDARY_MASTER_TYPE, "Secondary Host" },
|
|
{ PRIMARY_MASTER_TYPE, "Primary Host" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* Error Codes */
|
|
#define SESSION_CLOSED_ERROR 0
|
|
#define PRIMARY_SESSION_UNAVAILABLE_ERROR 1
|
|
#define SERVICE_UNAVAILABLE_ERROR 2
|
|
|
|
static const value_string hartip_error_code_values[] = {
|
|
{ SESSION_CLOSED_ERROR, "Session closed" },
|
|
{ PRIMARY_SESSION_UNAVAILABLE_ERROR, "Primary session unavailable" },
|
|
{ SERVICE_UNAVAILABLE_ERROR, "Service unavailable" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* Handle for statistics tap. */
|
|
static int hartip_tap = -1;
|
|
|
|
/* Structure used for passing data for statistics processing. */
|
|
typedef struct _hartip_tap_info {
|
|
gint8 message_type;
|
|
gint8 message_id;
|
|
} hartip_tap_info;
|
|
|
|
/* Names of items in statistics tree. */
|
|
static const gchar* st_str_packets = "Total HART_IP Packets";
|
|
static const gchar* st_str_requests = "Request Packets";
|
|
static const gchar* st_str_responses = "Response Packets";
|
|
static const gchar* st_str_publish = "Publish Packets";
|
|
static const gchar* st_str_errors = "Error Packets";
|
|
|
|
/* Handles of items in statistics tree. */
|
|
static int st_node_packets = -1;
|
|
static int st_node_requests = -1;
|
|
static int st_node_responses = -1;
|
|
static int st_node_publish = -1;
|
|
static int st_node_errors = -1;
|
|
|
|
static void
|
|
hartip_stats_tree_init(stats_tree* st)
|
|
{
|
|
st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
|
|
st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
|
|
st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, TRUE);
|
|
st_node_publish = stats_tree_create_node(st, st_str_publish, st_node_packets, TRUE);
|
|
st_node_errors = stats_tree_create_node(st, st_str_errors, st_node_packets, TRUE);
|
|
}
|
|
|
|
static int
|
|
hartip_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_,
|
|
epan_dissect_t* edt _U_, const void* p)
|
|
{
|
|
const hartip_tap_info *tapinfo = (const hartip_tap_info *)p;
|
|
const gchar *message_type_node_str, *message_id_node_str;
|
|
int message_type_node;
|
|
|
|
switch (tapinfo->message_type) {
|
|
case REQUEST_MSG_TYPE:
|
|
message_type_node_str = st_str_requests;
|
|
message_type_node = st_node_requests;
|
|
break;
|
|
case RESPONSE_MSG_TYPE:
|
|
message_type_node_str = st_str_responses;
|
|
message_type_node = st_node_responses;
|
|
break;
|
|
case PUBLISH_MSG_TYPE:
|
|
message_type_node_str = st_str_publish;
|
|
message_type_node = st_node_publish;
|
|
break;
|
|
case ERROR_MSG_TYPE:
|
|
case NAK_MSG_TYPE:
|
|
message_type_node_str = st_str_errors;
|
|
message_type_node = st_node_errors;
|
|
break;
|
|
default:
|
|
return 0; /* Don't want to track invalid messages for now. */
|
|
}
|
|
|
|
message_id_node_str = val_to_str(tapinfo->message_id,
|
|
hartip_message_id_values,
|
|
"Unknown message %d");
|
|
|
|
tick_stat_node(st, st_str_packets, 0, FALSE);
|
|
tick_stat_node(st, message_type_node_str, st_node_packets, FALSE);
|
|
tick_stat_node(st, message_id_node_str, message_type_node, FALSE);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static gint
|
|
dissect_empty_body(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb,
|
|
gint offset, gint bodylen)
|
|
{
|
|
proto_item *ti;
|
|
|
|
ti = proto_tree_add_item(tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
|
|
if (bodylen == 0) {
|
|
expert_add_info(pinfo, ti, &ei_hartip_data_none);
|
|
} else {
|
|
expert_add_info(pinfo, ti, &ei_hartip_data_unexpected);
|
|
}
|
|
return bodylen;
|
|
}
|
|
|
|
static gint
|
|
dissect_session_init(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
|
|
gint bodylen)
|
|
{
|
|
if (bodylen == 5) {
|
|
proto_tree_add_item(body_tree, hf_hartip_master_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item(body_tree, hf_hartip_inactivity_close_timer, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
} else {
|
|
proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
static gint
|
|
dissect_error(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen == 1) {
|
|
proto_tree_add_item(body_tree, hf_hartip_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
} else {
|
|
proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
static gint
|
|
dissect_session_close(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
|
|
gint offset, gint bodylen)
|
|
{
|
|
return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
|
|
}
|
|
|
|
static gint
|
|
dissect_keep_alive(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
|
|
gint offset, gint bodylen)
|
|
{
|
|
return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
|
|
}
|
|
|
|
static gint
|
|
dissect_byte(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
|
|
{
|
|
proto_tree_add_item(tree, hf, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
return 1;
|
|
}
|
|
|
|
static gint
|
|
dissect_short(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
|
|
{
|
|
proto_tree_add_item(tree, hf, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
return 2;
|
|
}
|
|
|
|
static gint
|
|
dissect_float(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
|
|
{
|
|
proto_tree_add_item(tree, hf, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
return 4;
|
|
}
|
|
|
|
static gint
|
|
dissect_packAscii(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset, int len)
|
|
{
|
|
gushort usIdx;
|
|
gushort usGroupCnt;
|
|
gushort usMaxGroups; /* Number of 4 byte groups to pack. */
|
|
gushort usMask;
|
|
gint iIndex;
|
|
gint i = 0;
|
|
gushort buf[4];
|
|
guint8 *tmp;
|
|
char *str = NULL;
|
|
|
|
tmp = (guint8 *)wmem_alloc0(wmem_packet_scope(), len);
|
|
tvb_memcpy(tvb, tmp, offset, len);
|
|
|
|
/* Maximum possible unpacked length = (len / 3) * 4 */
|
|
str = (char *)wmem_alloc(wmem_packet_scope(), ((len / 3) * 4)+1);
|
|
|
|
iIndex = 0;
|
|
usMaxGroups = (gushort)(len / 3);
|
|
for (usGroupCnt = 0; usGroupCnt < usMaxGroups; usGroupCnt++) {
|
|
/*
|
|
* First unpack 3 bytes into a group of 4 bytes, clearing bits 6 & 7.
|
|
*/
|
|
buf[0] = (gushort)(tmp[iIndex] >> 2);
|
|
buf[1] = (gushort)(((tmp[iIndex] << 4) & 0x30) | (tmp[iIndex + 1] >> 4));
|
|
buf[2] = (gushort)(((tmp[iIndex + 1] << 2) & 0x3C) | (tmp[iIndex + 2] >> 6));
|
|
buf[3] = (gushort)(tmp[iIndex + 2] & 0x3F);
|
|
iIndex += 3;
|
|
|
|
/*
|
|
* Now transfer to unpacked area, setting bit 6 to complement of bit 5.
|
|
*/
|
|
for (usIdx = 0; usIdx < 4; usIdx++) {
|
|
usMask = (gushort)(((buf[usIdx] & 0x20) << 1) ^ 0x40);
|
|
DISSECTOR_ASSERT(i < 256);
|
|
str[i++] = (gchar)(buf[usIdx] | usMask);
|
|
}
|
|
}
|
|
str[i] = '\0';
|
|
|
|
proto_tree_add_string(tree, hf, tvb, offset, len, str);
|
|
|
|
return len;
|
|
}
|
|
|
|
static gint
|
|
dissect_timestamp(proto_tree *tree, int hf, const char *name, int len,
|
|
tvbuff_t *tvb, gint offset)
|
|
{
|
|
proto_item *ti;
|
|
guint32 t;
|
|
guint32 hrs = 0;
|
|
guint32 mins = 0;
|
|
guint32 secs = 0;
|
|
guint32 ms = 0;
|
|
|
|
ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA);
|
|
t = tvb_get_ntohl(tvb, offset);
|
|
|
|
if (t > 0 ) {
|
|
t /= 32;
|
|
ms = t % 1000;
|
|
t /= 1000;
|
|
secs = t % 60;
|
|
t /= 60;
|
|
mins = t % 60;
|
|
hrs = (guint)(t / 60);
|
|
}
|
|
|
|
proto_item_set_text(ti, "%s: %02d:%02d:%02d.%03d", name, hrs, mins, secs, ms);
|
|
return len;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd0(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 12) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_expansion_code, tvb, offset);
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_expanded_device_type, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_req_min_preambles, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_hart_protocol_major_rev, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_device_rev, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_software_rev, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_hardware_rev_physical_signal, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_flage, tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_id, tvb, offset, 3, ENC_NA);
|
|
offset += 3;
|
|
|
|
if (bodylen >= 16) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_rsp_min_preambles, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_max_device_variables, tvb, offset);
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 18) {
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_manufacturer_Identification_code, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 22) {
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_private_label, tvb, offset);
|
|
/*offset += */dissect_byte(body_tree, hf_hartip_pt_rsp_device_profile, tvb, offset);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd1(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 5) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_units, tvb, offset);
|
|
/*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv, tvb, offset);
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd2(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 8) {
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
|
|
/*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv_percent_range, tvb, offset);
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd3(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 24) {
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_sv_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_sv, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_tv_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_tv, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_qv_units, tvb, offset);
|
|
/*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_qv, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd7(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 2) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address, tvb, offset);
|
|
dissect_byte(body_tree, hf_hartip_pt_rsp_loop_current_mode, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd8(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 4) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_primary_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_secondary_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_tertiary_var_classify, tvb, offset);
|
|
dissect_byte(body_tree, hf_hartip_pt_rsp_quaternary_var_classify, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd9(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 13) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot0_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var_status, tvb, offset);
|
|
|
|
if (bodylen >= 21) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot1_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 29) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot2_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 37) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot3_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 45) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot4_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 53) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot5_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 61) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot6_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 69) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var_classify, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot7_device_var_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var_status, tvb, offset);
|
|
}
|
|
|
|
dissect_timestamp(body_tree, hf_hartip_pt_rsp_slot0_timestamp, "Slot0 Data TimeStamp", 4, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd13(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 21) {
|
|
offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 6);
|
|
offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_packed_descriptor, tvb, offset, 12);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_day, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_month, tvb, offset);
|
|
/*offset += */dissect_byte(body_tree, hf_hartip_pt_rsp_year, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd14(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 16) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_transducer_serial_number, tvb, offset, 3, ENC_NA);
|
|
offset += 3;
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_transducer_limit_min_span_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_upper_transducer_limit, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_lower_transducer_limit, tvb, offset);
|
|
dissect_float(body_tree, hf_hartip_pt_rsp_minimum_span, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd15(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 18) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_alarm_selection_code, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_transfer_function_code, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_upper_range_value, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_lower_range_value, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_damping_value, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_write_protect_code, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_reserved, tvb, offset);
|
|
dissect_byte(body_tree, hf_hartip_pt_rsp_pv_analog_channel_flags, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd16(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 3) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_final_assembly_number, tvb, offset, 3, ENC_NA);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd33(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 6) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot0_device_var_value, tvb, offset);
|
|
|
|
if (bodylen >= 12) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot1_device_var_value, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 18) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_units, tvb, offset);
|
|
offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot2_device_var_value, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 24) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_units, tvb, offset);
|
|
dissect_float(body_tree, hf_hartip_pt_rsp_slot3_device_var_value, tvb, offset);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd38(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 2) {
|
|
dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter, tvb, offset);
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd48(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 6) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 6, ENC_NA);
|
|
offset += 6;
|
|
|
|
if (bodylen >= 9) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_device_op_mode, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_0, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 13) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_1, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_saturated, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_2, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_3, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 14) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_fixed, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 24) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 11, ENC_NA);
|
|
/*offset += 11;*/
|
|
}
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd77(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
guint8 byte_count;
|
|
gint length = bodylen;
|
|
|
|
if (length >= 6) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_io_card, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_channel, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd_delimiter, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd, tvb, offset);
|
|
|
|
byte_count = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 6;
|
|
|
|
if ((byte_count >= 2) && (length >= 2) && (byte_count <= length)) {
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_device_status, tvb, offset);
|
|
length -= 2;
|
|
byte_count -= 2;
|
|
|
|
if ((byte_count > 0) && (length > 0) && (byte_count <= length)) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
|
|
byte_count, ENC_NA);
|
|
}
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd178(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
guint16 cmd;
|
|
guint8 number_of_cmds;
|
|
guint8 cmd_byte_count;
|
|
gint length = bodylen;
|
|
gint8 i;
|
|
gint result;
|
|
|
|
if (length >= 5) {
|
|
number_of_cmds = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_uint(body_tree, hf_hartip_pt_rsp_number_of_commands, tvb, offset, 1, number_of_cmds);
|
|
offset += 1;
|
|
length -= 1;
|
|
|
|
for (i = 0; i < number_of_cmds; i++)
|
|
{
|
|
if (length >= 4)
|
|
{
|
|
cmd = tvb_get_ntohs(tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
length -= 2;
|
|
|
|
cmd_byte_count = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 1;
|
|
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
|
|
length -= 1;
|
|
cmd_byte_count -= 1;
|
|
|
|
if ((cmd_byte_count > 0) && (length > 0) && (cmd_byte_count <= length))
|
|
{
|
|
switch(cmd)
|
|
{
|
|
case 3:
|
|
result = dissect_cmd3(body_tree, tvb, offset, cmd_byte_count);
|
|
break;
|
|
case 9:
|
|
result = dissect_cmd9(body_tree, tvb, offset, cmd_byte_count);
|
|
break;
|
|
case 48:
|
|
result = dissect_cmd48(body_tree, tvb, offset, cmd_byte_count);
|
|
break;
|
|
default:
|
|
result = 0;
|
|
break;
|
|
}
|
|
|
|
if (result == 0 ) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
|
|
cmd_byte_count, ENC_NA);
|
|
}
|
|
|
|
offset += cmd_byte_count;
|
|
length -= cmd_byte_count;
|
|
}
|
|
} else {
|
|
return bodylen;
|
|
}
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd203(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
if (bodylen >= 8) {
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_index_of_first_discrete_var, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_number_of_discrete_vars, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
|
|
dissect_timestamp(body_tree, hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
|
|
"TimeStamp for Most Recent Discrete Change", 4, tvb, offset);
|
|
offset += 4;
|
|
|
|
if (bodylen >= 11)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_state, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 14)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_state, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 17)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_state, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 20)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_state, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 23)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_state, tvb, offset);
|
|
offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
if (bodylen >= 26)
|
|
{
|
|
offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_state, tvb, offset);
|
|
dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_status, tvb, offset);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_cmd31(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
|
|
{
|
|
gint length = bodylen;
|
|
gint result = 0;
|
|
guint16 cmd;
|
|
|
|
if (length >= 2) {
|
|
cmd = tvb_get_ntohs(tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
length -= 2;
|
|
|
|
if (length > 0) {
|
|
switch(cmd)
|
|
{
|
|
case 64386:
|
|
result = dissect_cmd203(body_tree, tvb, offset, length);
|
|
break;
|
|
}
|
|
|
|
if (result == 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
|
|
length, ENC_NA);
|
|
}
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_parse_hart_cmds(proto_tree *body_tree, tvbuff_t *tvb, guint8 cmd,
|
|
gint offset, gint bodylen)
|
|
{
|
|
switch(cmd)
|
|
{
|
|
case 0:
|
|
case 11:
|
|
case 21:
|
|
return dissect_cmd0(body_tree, tvb, offset, bodylen);
|
|
case 1:
|
|
return dissect_cmd1(body_tree, tvb, offset, bodylen);
|
|
case 2:
|
|
return dissect_cmd2(body_tree, tvb, offset, bodylen);
|
|
case 3:
|
|
return dissect_cmd3(body_tree, tvb, offset, bodylen);
|
|
case 6:
|
|
case 7:
|
|
return dissect_cmd7(body_tree, tvb, offset, bodylen);
|
|
case 8:
|
|
return dissect_cmd8(body_tree, tvb, offset, bodylen);
|
|
case 9:
|
|
return dissect_cmd9(body_tree, tvb, offset, bodylen);
|
|
case 12:
|
|
case 17:
|
|
if (bodylen >= 24)
|
|
return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, tvb, offset, 24);
|
|
break;
|
|
case 13:
|
|
case 18:
|
|
return dissect_cmd13(body_tree, tvb, offset, bodylen);
|
|
case 14:
|
|
return dissect_cmd14(body_tree, tvb, offset, bodylen);
|
|
case 15:
|
|
return dissect_cmd15(body_tree, tvb, offset, bodylen);
|
|
case 16:
|
|
case 19:
|
|
return dissect_cmd16(body_tree, tvb, offset, bodylen);
|
|
case 20:
|
|
case 22:
|
|
if (bodylen >= 32) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 32,
|
|
ENC_ASCII|ENC_NA);
|
|
return 32;
|
|
}
|
|
break;
|
|
case 31:
|
|
return dissect_cmd31(body_tree, tvb, offset, bodylen);
|
|
case 33:
|
|
return dissect_cmd33(body_tree, tvb, offset, bodylen);
|
|
case 38:
|
|
return dissect_cmd38(body_tree, tvb, offset, bodylen);
|
|
case 48:
|
|
return dissect_cmd48(body_tree, tvb, offset, bodylen);
|
|
case 77:
|
|
return dissect_cmd77(body_tree, tvb, offset, bodylen);
|
|
case 178:
|
|
return dissect_cmd178(body_tree, tvb, offset, bodylen);
|
|
case 203:
|
|
return dissect_cmd203(body_tree, tvb, offset, bodylen);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
dissect_pass_through(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
|
|
gint bodylen)
|
|
{
|
|
proto_item *ti;
|
|
guint8 delimiter;
|
|
const char *frame_type_str;
|
|
guint8 cmd = 0;
|
|
gint length = bodylen;
|
|
gint is_short = 0;
|
|
gint is_rsp = 0;
|
|
gint num_preambles = 0;
|
|
gint result;
|
|
guint8 short_addr;
|
|
|
|
/* find number of preambles */
|
|
while (length > num_preambles) {
|
|
delimiter = tvb_get_guint8(tvb, offset + num_preambles);
|
|
if (delimiter != 0xFF)
|
|
break;
|
|
|
|
num_preambles += 1;
|
|
}
|
|
|
|
if (num_preambles > 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_preambles, tvb, offset,
|
|
num_preambles, ENC_NA);
|
|
offset += num_preambles;
|
|
length -= num_preambles;
|
|
}
|
|
|
|
if (length > 0) {
|
|
delimiter = tvb_get_guint8(tvb, offset);
|
|
ti = proto_tree_add_uint(body_tree, hf_hartip_pt_delimiter, tvb, offset, 1,
|
|
delimiter);
|
|
offset += 1;
|
|
length -= 1;
|
|
|
|
if ((delimiter & 0x7) == 2) {
|
|
frame_type_str = "STX";
|
|
} else if ((delimiter & 0x7) == 6) {
|
|
frame_type_str = "ACK";
|
|
is_rsp = 1;
|
|
} else if ((delimiter & 0x7) == 1) {
|
|
frame_type_str = "PUB";
|
|
is_rsp = 1;
|
|
} else {
|
|
frame_type_str = "UNK";
|
|
}
|
|
|
|
if ((delimiter & 0x80) == 0) {
|
|
is_short = 1;
|
|
proto_item_set_text(ti, "Short Address, Frame Type: %s", frame_type_str);
|
|
} else {
|
|
proto_item_set_text(ti, "Frame Type: %s", frame_type_str);
|
|
}
|
|
}
|
|
|
|
if (is_short == 1) {
|
|
if (length > 0) {
|
|
short_addr = tvb_get_guint8(tvb, offset);
|
|
short_addr = short_addr & 0x3F;
|
|
proto_tree_add_uint(body_tree, hf_hartip_pt_short_addr, tvb, offset, 1,
|
|
short_addr);
|
|
offset += 1;
|
|
length -= 1;
|
|
}
|
|
} else {
|
|
if (length > 4) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_long_addr, tvb, offset, 5, ENC_NA);
|
|
offset += 5;
|
|
length -= 5;
|
|
} else if (length > 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, length, ENC_NA);
|
|
length = 0;
|
|
}
|
|
}
|
|
|
|
if (length > 0) {
|
|
cmd = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_command, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 1;
|
|
}
|
|
if (length > 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_length, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 1;
|
|
}
|
|
|
|
if (is_rsp == 1) {
|
|
if (length > 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 1;
|
|
}
|
|
if (length > 0) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_device_status, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
length -= 1;
|
|
}
|
|
}
|
|
|
|
if (length > 1) {
|
|
result = dissect_parse_hart_cmds(body_tree, tvb, cmd, offset, (length - 1));
|
|
if (result == 0 ) {
|
|
proto_tree_add_item(body_tree, hf_hartip_pt_payload, tvb, offset,
|
|
(length - 1), ENC_NA);
|
|
}
|
|
offset += (length - 1);
|
|
length = 1;
|
|
}
|
|
if (length > 0) {
|
|
proto_tree_add_checksum(body_tree, tvb, offset, hf_hartip_pt_checksum, -1, NULL, NULL, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
|
|
}
|
|
|
|
return bodylen;
|
|
}
|
|
|
|
static void
|
|
hartip_set_conversation(packet_info *pinfo)
|
|
{
|
|
conversation_t *conversation = NULL;
|
|
|
|
if (!pinfo->fd->flags.visited && (pinfo->ptype == PT_UDP)) {
|
|
/*
|
|
* This function is called for a session initiate send over UDP.
|
|
* The session initiate is sent to the server on port HARTIP_PORT.
|
|
* The server then responds from a different port. All subsequent
|
|
* communication for the session between the client and server
|
|
* uses the new server port and the original client port.
|
|
*
|
|
* A new conversation is created here and this dissector is set to
|
|
* be used for it. This allows the packets to be dissected properly
|
|
* for this protocol.
|
|
*/
|
|
conversation = find_conversation(pinfo->num,
|
|
&pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
|
|
pinfo->srcport, 0, NO_PORT_B);
|
|
if( (conversation == NULL) ||
|
|
(conversation_get_dissector(conversation, pinfo->num) != hartip_udp_handle) ) {
|
|
conversation = conversation_new(pinfo->num,
|
|
&pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
|
|
pinfo->srcport, 0, NO_PORT2);
|
|
conversation_set_dissector(conversation, hartip_udp_handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
dissect_hartip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
gint offset)
|
|
{
|
|
proto_tree *hartip_tree, *hdr_tree, *body_tree;
|
|
proto_item *hart_item;
|
|
gint bodylen;
|
|
guint8 message_type, message_id;
|
|
guint16 transaction_id, length;
|
|
const char *msg_id_str, *msg_type_str;
|
|
hartip_tap_info *tapinfo;
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "HART_IP");
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
length = tvb_get_ntohs(tvb, offset+6);
|
|
|
|
hart_item = proto_tree_add_item(tree, proto_hartip, tvb, 0, length, ENC_NA);
|
|
hartip_tree = proto_item_add_subtree(hart_item, ett_hartip);
|
|
|
|
hdr_tree = proto_tree_add_subtree(hartip_tree, tvb, offset, HARTIP_HEADER_LENGTH,
|
|
ett_hartip_hdr, NULL, "HART_IP Header");
|
|
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
message_type = tvb_get_guint8(tvb, offset);
|
|
msg_type_str = val_to_str(message_type, hartip_message_type_values, "Unknown message type %d");
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
message_id = tvb_get_guint8(tvb, offset);
|
|
msg_id_str = val_to_str(message_id, hartip_message_id_values, "Unknown message %d");
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_id, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* Setup statistics for tap. */
|
|
tapinfo = wmem_new(wmem_packet_scope(), hartip_tap_info);
|
|
tapinfo->message_type = message_type;
|
|
tapinfo->message_id = message_id;
|
|
tap_queue_packet(hartip_tap, pinfo, tapinfo);
|
|
|
|
if (message_id == SESSION_INITIATE_ID) {
|
|
hartip_set_conversation(pinfo);
|
|
}
|
|
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_status, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
transaction_id = tvb_get_ntohs(tvb, offset);
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_item_append_text(hart_item, ", %s %s, Sequence Number %d", msg_id_str,
|
|
msg_type_str, transaction_id);
|
|
|
|
col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ",
|
|
"%s %s, Sequence Number %d",
|
|
msg_id_str, msg_type_str, transaction_id);
|
|
col_set_fence(pinfo->cinfo, COL_INFO);
|
|
|
|
proto_tree_add_item(hdr_tree, hf_hartip_hdr_msg_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
if (length < HARTIP_HEADER_LENGTH)
|
|
return tvb_reported_length(tvb);
|
|
bodylen = length - HARTIP_HEADER_LENGTH;
|
|
|
|
/* add body elements. */
|
|
body_tree = proto_tree_add_subtree_format(hartip_tree, tvb, offset, bodylen,
|
|
ett_hartip_body, NULL,
|
|
"HART_IP Body, %s, %s", msg_id_str, msg_type_str);
|
|
|
|
if ((message_type == ERROR_MSG_TYPE) ||
|
|
(message_type == NAK_MSG_TYPE)) {
|
|
offset += dissect_error(body_tree, tvb, offset, bodylen);
|
|
} else {
|
|
/* Dissect the various HARTIP messages. */
|
|
switch(message_id) {
|
|
case SESSION_INITIATE_ID:
|
|
offset += dissect_session_init(body_tree, tvb, offset, bodylen);
|
|
break;
|
|
case SESSION_CLOSE_ID:
|
|
offset += dissect_session_close(body_tree, pinfo, tvb, offset, bodylen);
|
|
break;
|
|
case KEEP_ALIVE_ID:
|
|
offset += dissect_keep_alive(body_tree, pinfo, tvb, offset, bodylen);
|
|
break;
|
|
case PASS_THROUGH_ID:
|
|
offset += dissect_pass_through(body_tree, tvb, offset, bodylen);
|
|
break;
|
|
default:
|
|
proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
|
|
offset += bodylen;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static guint
|
|
get_dissect_hartip_len(packet_info *pinfo _U_, tvbuff_t *tvb,
|
|
int offset, void *data _U_)
|
|
{
|
|
return tvb_get_ntohs(tvb, offset+6);
|
|
}
|
|
|
|
static int
|
|
dissect_hartip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|
{
|
|
return dissect_hartip_common(tvb, pinfo, tree, 0);
|
|
}
|
|
|
|
static int
|
|
dissect_hartip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
void *data)
|
|
{
|
|
tcp_dissect_pdus(tvb, pinfo, tree, hartip_desegment, HARTIP_HEADER_LENGTH,
|
|
get_dissect_hartip_len, dissect_hartip_pdu, data);
|
|
return tvb_reported_length(tvb);
|
|
}
|
|
|
|
static int
|
|
dissect_hartip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
void *data _U_)
|
|
{
|
|
gint offset = 0;
|
|
|
|
while (tvb_reported_length_remaining(tvb, offset) >= HARTIP_HEADER_LENGTH)
|
|
offset += dissect_hartip_common(tvb, pinfo, tree, offset);
|
|
|
|
return offset;
|
|
}
|
|
|
|
void
|
|
proto_register_hartip(void)
|
|
{
|
|
static hf_register_info hf[] = {
|
|
/* HARTIP header elements. */
|
|
{ &hf_hartip_hdr_version,
|
|
{ "Version", "hart_ip.version",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"HART_IP version number", HFILL }
|
|
},
|
|
{ &hf_hartip_hdr_message_type,
|
|
{ "Message Type", "hart_ip.message_type",
|
|
FT_UINT8, BASE_DEC, VALS(hartip_message_type_values), 0,
|
|
"HART_IP message type", HFILL }
|
|
},
|
|
{ &hf_hartip_hdr_message_id,
|
|
{ "Message ID", "hart_ip.message_id",
|
|
FT_UINT8, BASE_DEC, VALS(hartip_message_id_values), 0,
|
|
"HART_IP message id", HFILL }
|
|
},
|
|
{ &hf_hartip_hdr_status,
|
|
{ "Status", "hart_ip.status",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"HART_IP status field", HFILL }
|
|
},
|
|
{ &hf_hartip_hdr_transaction_id,
|
|
{ "Sequence Number", "hart_ip.transaction_id",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"HART_IP Sequence Number", HFILL }
|
|
},
|
|
{ &hf_hartip_hdr_msg_length,
|
|
{ "Message Length", "hart_ip.msg_length",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"HART_IP Message Length", HFILL }
|
|
},
|
|
|
|
/* HARTIP Body elements */
|
|
{ &hf_hartip_data,
|
|
{ "Message Data", "hart_ip.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
"HART_IP Message Data", HFILL }
|
|
},
|
|
{ &hf_hartip_master_type,
|
|
{ "Host Type", "hart_ip.session_init.master_type",
|
|
FT_UINT8, BASE_DEC, VALS(hartip_master_type_values), 0xFF,
|
|
"Session Host Type", HFILL }
|
|
},
|
|
{ &hf_hartip_inactivity_close_timer,
|
|
{ "Inactivity Close Timer", "hart_ip.session_init.inactivity_close_timer",
|
|
FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"Session Inactivity Close Timer", HFILL }
|
|
},
|
|
{ &hf_hartip_error_code,
|
|
{ "Error", "hart_ip.error.error_code",
|
|
FT_UINT8, BASE_DEC, VALS(hartip_error_code_values), 0xFF,
|
|
"Error Code", HFILL }
|
|
},
|
|
|
|
/* HARTIP Pass-through commads. */
|
|
{ &hf_hartip_pt_preambles,
|
|
{ "Preambles", "hart_ip.pt.preambles",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
"Pass Through Preambles", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_delimiter,
|
|
{ "Delimter", "hart_ip.pt.delimter",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
"Pass Through Delimiter", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_short_addr,
|
|
{ "Short Address", "hart_ip.pt.short_addr",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"Pass Through Short Address", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_long_addr,
|
|
{ "Long Address", "hart_ip.pt.long_address",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
"Pass Through Long Address", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_command,
|
|
{ "Command", "hart_ip.pt.command",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"Pass Through Command", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_length,
|
|
{ "Length", "hart_ip.pt.length",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"Pass Through Length", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_response_code,
|
|
{ "Response Code", "hart_ip.pt.response_code",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
"Pass Through Response Code", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_device_status,
|
|
{ "Device Status", "hart_ip.pt.device_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
"Pass Through Device Status", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_payload,
|
|
{ "Payload", "hart_ip.pt.payload",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
"Pass Through Payload", HFILL }
|
|
},
|
|
{ &hf_hartip_pt_checksum,
|
|
{ "Checksum", "hart_ip.pt.checksum",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
"Pass Through Checksum", HFILL }
|
|
},
|
|
|
|
/* add fields for universal commands. */
|
|
/* command 0 */
|
|
{ &hf_hartip_pt_rsp_expansion_code,
|
|
{ "Expansion Code", "hart_ip.pt.rsp.expansion_code",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_expanded_device_type,
|
|
{ "Expanded Device Type", "hart_ip.pt.rsp.expanded_device_type",
|
|
FT_UINT16, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_req_min_preambles,
|
|
{ "Minimum Number of Request Preambles", "hart_ip.pt.rsp.req_min_preambles",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_hart_protocol_major_rev,
|
|
{ "HART Universal Revision", "hart_ip.pt.rsp.hart_univ_rev",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_device_rev,
|
|
{ "Device Revision", "hart_ip.pt.rsp.device_rev",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_software_rev,
|
|
{ "Device Software Revision", "hart_ip.pt.rsp.software_rev",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_hardware_rev_physical_signal,
|
|
{ "Hardware Rev and Physical Signaling", "hart_ip.pt.rsp.hardrev_and_physical_signal",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_flage,
|
|
{ "Flags", "hart_ip.pt.rsp.flags",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_device_id,
|
|
{ "Device ID", "hart_ip.pt.rsp.device_id",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_rsp_min_preambles,
|
|
{ "Minimum Number of Response Preambles", "hart_ip.pt.rsp.rsp_min_preambles",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_max_device_variables,
|
|
{ "Maximum Number of Device Variables", "hart_ip.pt.rsp.device_variables",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_configuration_change_counter,
|
|
{ "Configuration Change Counter", "hart_ip.pt.rsp.configure_change",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_extended_device_status,
|
|
{ "Extended Device Status", "hart_ip.pt.rsp.ext_device_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_manufacturer_Identification_code,
|
|
{ "Manufacturer ID", "hart_ip.pt.rsp.manufacturer_Id",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_private_label,
|
|
{ "Private Label", "hart_ip.pt.rsp.private_label",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_device_profile,
|
|
{ "Device Profile", "hart_ip.pt.rsp.device_profile",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 2 */
|
|
{ &hf_hartip_pt_rsp_pv_percent_range,
|
|
{ "PV Percent Range", "hart_ip.pt.rsp.pv_percent_range",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 3 */
|
|
{ &hf_hartip_pt_rsp_pv_loop_current,
|
|
{ "PV Loop Current", "hart_ip.pt.rsp.pv_loop_current",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_units,
|
|
{ "PV Units", "hart_ip.pt.rsp.pv_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv,
|
|
{ "PV", "hart_ip.pt.rsp.pv",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_sv_units,
|
|
{ "SV Units", "hart_ip.pt.rsp.sv_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_sv,
|
|
{ "SV", "hart_ip.pt.rsp.sv",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_tv_units,
|
|
{ "TV Units", "hart_ip.pt.rsp.tv_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_tv,
|
|
{ "TV", "hart_ip.pt.rsp.tv",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_qv_units,
|
|
{ "QV Units", "hart_ip.pt.rsp.qv_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_qv,
|
|
{ "QV", "hart_ip.pt.rsp.qv",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 7 */
|
|
{ &hf_hartip_pt_rsp_loop_current_mode,
|
|
{ "Loop Current Mode", "hart_ip.pt.rsp.loop_current_mode",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 8 */
|
|
{ &hf_hartip_pt_rsp_primary_var_classify,
|
|
{ "Primary Variable Classification", "hart_ip.pt.rsp.primary_variable_classification",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_secondary_var_classify,
|
|
{ "Secondary Variable Classification", "hart_ip.pt.rsp.secondary_variable_classification",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_tertiary_var_classify,
|
|
{ "Tertiary Variable Classification", "hart_ip.pt.rsp.tertiary_variable_classification",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_quaternary_var_classify,
|
|
{ "Quaternary Variable Classification", "hart_ip.pt.rsp.quaternary_variable_classification",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 9 */
|
|
{ &hf_hartip_pt_rsp_slot0_device_var,
|
|
{ "Slot0 Device Variable", "hart_ip.pt.rsp.slot0_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_device_var_classify,
|
|
{ "Slot0 Device Variable Classification", "hart_ip.pt.rsp.slot0_device_var_classification",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_units,
|
|
{ "Slot0 Units", "hart_ip.pt.rsp.slot0_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_device_var_value,
|
|
{ "Slot0 Device Variable Value", "hart_ip.pt.rsp.slot0_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_device_var_status,
|
|
{ "Slot0 Device Variable Status", "hart_ip.pt.rsp.slot0_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_device_var,
|
|
{ "Slot1 Device Variable", "hart_ip.pt.rsp.slot1_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_device_var_classify,
|
|
{ "Slot1 Device Variable Classification", "hart_ip.pt.rsp.slot1_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_units,
|
|
{ "Slot1 Units", "hart_ip.pt.rsp.slot1_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_device_var_value,
|
|
{ "Slot1 Device Variable Value", "hart_ip.pt.rsp.slot1_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_device_var_status,
|
|
{ "Slot1 Device Variable Status", "hart_ip.pt.rsp.slot1_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_device_var,
|
|
{ "Slot2 Device Variable", "hart_ip.pt.rsp.slot2_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_device_var_classify,
|
|
{ "Slot2 Device Variable Classification", "hart_ip.pt.rsp.slot2_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_units,
|
|
{ "Slot2 Units", "hart_ip.pt.rsp.slot2_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_device_var_value,
|
|
{ "Slot2 Device Variable Value", "hart_ip.pt.rsp.slot2_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_device_var_status,
|
|
{ "Slot2 Device Variable Status", "hart_ip.pt.rsp.slot2_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_device_var,
|
|
{ "Slot3 Device Variable", "hart_ip.pt.rsp.slot3_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_device_var_classify,
|
|
{ "Slot3 Device Variable Classification", "hart_ip.pt.rsp.slot3_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_units,
|
|
{ "Slot3 Units", "hart_ip.pt.rsp.slot3_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_device_var_value,
|
|
{ "Slot3 Device Variable Value", "hart_ip.pt.rsp.slot3_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_device_var_status,
|
|
{ "Slot3 Device Variable Status", "hart_ip.pt.rsp.slot3_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_device_var,
|
|
{ "Slot4 Device Variable", "hart_ip.pt.rsp.slot4_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_device_var_classify,
|
|
{ "Slot4 Device Variable Classification", "hart_ip.pt.rsp.slot4_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_units,
|
|
{ "Slot4 Units", "hart_ip.pt.rsp.slot4_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_device_var_value,
|
|
{ "Slot4 Device Variable Value", "hart_ip.pt.rsp.slot4_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_device_var_status,
|
|
{ "Slot4 Device Variable Status", "hart_ip.pt.rsp.slot4_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_device_var,
|
|
{ "Slot5 Device Variable", "hart_ip.pt.rsp.slot5_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_device_var_classify,
|
|
{ "Slot5 Device Variable Classification", "hart_ip.pt.rsp.slot5_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_units,
|
|
{ "Slot5 Units", "hart_ip.pt.rsp.slot5_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_device_var_value,
|
|
{ "Slot5 Device Variable Value", "hart_ip.pt.rsp.slot5_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_device_var_status,
|
|
{ "Slot5 Device Variable Status", "hart_ip.pt.rsp.slot5_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot6_device_var,
|
|
{ "Slot6 Device Variable", "hart_ip.pt.rsp.slot6_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot6_device_var_classify,
|
|
{ "Slot6 Device Variable Classification", "hart_ip.pt.rsp.slot6_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot6_units,
|
|
{ "Slot6 Units", "hart_ip.pt.rsp.slot6_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot6_device_var_value,
|
|
{ "Slot6 Device Variable Value", "hart_ip.pt.rsp.slot6_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot6_device_var_status,
|
|
{ "Slot6 Device Variable Status", "hart_ip.pt.rsp.slot6_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot7_device_var,
|
|
{ "Slot7 Device Variable", "hart_ip.pt.rsp.slot7_device_var",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot7_device_var_classify,
|
|
{ "Slot7 Device Variable Classification", "hart_ip.pt.rsp.slot7_device_var_classify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot7_units,
|
|
{ "Slot7 Units", "hart_ip.pt.rsp.slot7_units",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot7_device_var_value,
|
|
{ "Slot7 Device Variable Value", "hart_ip.pt.rsp.slot7_device_var_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot7_device_var_status,
|
|
{ "Slot7 Device Variable Status", "hart_ip.pt.rsp.slot7_device_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_timestamp,
|
|
{ "Slot0 Data TimeStamp", "hart_ip.pt.rsp.slot0_data_timestamp",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 13 */
|
|
{ &hf_hartip_pt_rsp_packed_descriptor,
|
|
{ "Descriptor", "hart_ip.pt.rsp.descriptor",
|
|
FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_day,
|
|
{ "Day", "hart_ip.pt.rsp.day",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_month,
|
|
{ "Month", "hart_ip.pt.rsp.month",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_year,
|
|
{ "Year", "hart_ip.pt.rsp.year",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 14 */
|
|
{ &hf_hartip_pt_rsp_transducer_serial_number,
|
|
{ "Transducer Serail Number", "hart_ip.pt.rsp.transducer_serail_number",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_transducer_limit_min_span_units,
|
|
{ "Transducer Limit Min Span Units", "hart_ip.pt.rsp.transducer_limit_min_span_units",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_upper_transducer_limit,
|
|
{ "Upper Transducer Limit", "hart_ip.pt.rsp.upper_transducer_limit",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_lower_transducer_limit,
|
|
{ "Lower Transducer Limit", "hart_ip.pt.rsp.lower_transducer_limit",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_minimum_span,
|
|
{ "Minimum Span", "hart_ip.pt.rsp.minimum_span",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 15 */
|
|
{ &hf_hartip_pt_rsp_pv_alarm_selection_code,
|
|
{ "PV Alarm Selection Code", "hart_ip.pt.rsp.pv_alarm_selection_code",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_transfer_function_code,
|
|
{ "PV Transfer Function Code", "hart_ip.pt.rsp.pv_transfer_function_code",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units,
|
|
{ "PV Upper and Lower Range Values Units", "hart_ip.pt.rsp.pv_upper_and_lower_range_values_units",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_upper_range_value,
|
|
{ "PV Upper Range Value", "hart_ip.pt.rsp.pv_upper_range_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_lower_range_value,
|
|
{ "PV Lower Range Value", "hart_ip.pt.rsp.pv_lower_range_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_damping_value,
|
|
{ "PV Damping Value", "hart_ip.pt.rsp.pv_damping_value",
|
|
FT_FLOAT, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_write_protect_code,
|
|
{ "Write Protect Code", "hart_ip.pt.rsp.write_protect_code",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_reserved,
|
|
{ "Reserved", "hart_ip.pt.rsp.reserved",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_pv_analog_channel_flags,
|
|
{ "PV Analog Channel Flags", "hart_ip.pt.rsp.pv_analog_channel_flags",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 16 and 19 */
|
|
{ &hf_hartip_pt_rsp_final_assembly_number,
|
|
{ "Final Assembly Number", "hart_ip.pt.rsp.final_assembly_numbe",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* Tag */
|
|
{ &hf_hartip_pt_rsp_tag,
|
|
{ "Tag", "hart_ip.pt.rsp.tag",
|
|
FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* Message */
|
|
{ &hf_hartip_pt_rsp_message,
|
|
{ "Message", "hart_ip.pt.rsp.message",
|
|
FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 48 */
|
|
{ &hf_hartip_pt_rsp_device_sp_status,
|
|
{ "Device-Specific Status", "hart_ip.pt.rsp.device_sp_status",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_device_op_mode,
|
|
{ "Device Operating Mode", "hart_ip.pt.rsp.device_op_mode",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_standardized_status_0,
|
|
{ "Standardized Status 0", "hart_ip.pt.rsp.standardized_status_0",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_standardized_status_1,
|
|
{ "Standardized Status 1", "hart_ip.pt.rsp.standardized_status_1",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_analog_channel_saturated,
|
|
{ "Analog Channel Saturated", "hart_ip.pt.rsp.analog_channel_saturated",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_standardized_status_2,
|
|
{ "Standardized Status 2", "hart_ip.pt.rsp.standardized_status_2",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_standardized_status_3,
|
|
{ "Standardized Status 3", "hart_ip.pt.rsp.standardized_status_3",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_analog_channel_fixed,
|
|
{ "Analog Channel Fixed", "hart_ip.pt.rsp.analog_channel_fixed",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 77 */
|
|
{ &hf_hartip_pt_rsp_io_card,
|
|
{ "IO Card", "hart_ip.pt.rsp.io_card",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_channel,
|
|
{ "Channel", "hart_ip.pt.rsp.channel",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_embedded_cmd_delimiter,
|
|
{ "Embedded Command Delimter", "hart_ip.pt.rsp.embedded_command_delimter",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_poll_address,
|
|
{ "Poll Address", "hart_ip.pt.rsp.poll_address",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_embedded_cmd,
|
|
{ "Embedded Command", "hart_ip.pt.rsp.embedded_command",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 178 */
|
|
{ &hf_hartip_pt_rsp_number_of_commands,
|
|
{ "Number of Commands", "hart_ip.pt.rsp.number_of_commands",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
/* command 31 and 178 */
|
|
{ &hf_hartip_pt_rsp_command_number,
|
|
{ "Command number", "hart_ip.pt.rsp.command_number",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_data,
|
|
{ "Data", "hart_ip.pt.rsp.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
/* command 77 and 178 */
|
|
{ &hf_hartip_pt_rsp_command_byte_count,
|
|
{ "Command byte count", "hart_ip.pt.rsp.command_byte_count",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
|
|
/* command 203 */
|
|
{ &hf_hartip_pt_rsp_index_of_first_discrete_var,
|
|
{ "Index of First Discrete Variable", "hart_ip.pt.rsp.index_of_first_discrete_var",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_number_of_discrete_vars,
|
|
{ "Number of Discrete Variables", "hart_ip.pt.rsp.number_of_discrete_vars",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
|
|
{ "TimeStamp for Most Recent Discrete Change", "hart_ip.pt.rsp.timestamp_for_most_recent_discrete_change",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_discrete_var_state,
|
|
{ "Slot0 Discrete Variable State", "hart_ip.pt.rsp.slot0_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot0_discrete_var_status,
|
|
{ "Slot0 Discrete Variable Status", "hart_ip.pt.rsp.slot0_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_discrete_var_state,
|
|
{ "Slot1 Discrete Variable State", "hart_ip.pt.rsp.slot1_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot1_discrete_var_status,
|
|
{ "Slot1 Discrete Variable Status", "hart_ip.pt.rsp.slot1_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_discrete_var_state,
|
|
{ "Slot2 Discrete Variable State", "hart_ip.pt.rsp.slot2_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot2_discrete_var_status,
|
|
{ "Slot2 Discrete Variable Status", "hart_ip.pt.rsp.slot2_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_discrete_var_state,
|
|
{ "Slot3 Discrete Variable State", "hart_ip.pt.rsp.slot3_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot3_discrete_var_status,
|
|
{ "Slot3 Discrete Variable Status", "hart_ip.pt.rsp.slot3_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_discrete_var_state,
|
|
{ "Slot4 Discrete Variable State", "hart_ip.pt.rsp.slot4_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot4_discrete_var_status,
|
|
{ "Slot4 Discrete Variable Status", "hart_ip.pt.rsp.slot4_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_discrete_var_state,
|
|
{ "Slot5 Discrete Variable State", "hart_ip.pt.rsp.slot5_discrete_var_state",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }
|
|
},
|
|
{ &hf_hartip_pt_rsp_slot5_discrete_var_status,
|
|
{ "Slot5 Discrete Variable Status", "hart_ip.pt.rsp.slot5_discrete_var_status",
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }
|
|
}
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
&ett_hartip,
|
|
&ett_hartip_hdr,
|
|
&ett_hartip_body
|
|
};
|
|
|
|
static ei_register_info ei[] = {
|
|
{ &ei_hartip_data_none, { "hart_ip.data.none", PI_PROTOCOL, PI_NOTE, "No data", EXPFILL }},
|
|
{ &ei_hartip_data_unexpected, { "hart_ip.data.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected message body", EXPFILL }},
|
|
};
|
|
|
|
module_t *hartip_module;
|
|
expert_module_t* expert_hartip;
|
|
|
|
proto_hartip = proto_register_protocol("HART_IP Protocol", "HART_IP", "hart_ip");
|
|
proto_register_field_array(proto_hartip, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
expert_hartip = expert_register_protocol(proto_hartip);
|
|
expert_register_field_array(expert_hartip, ei, array_length(ei));
|
|
|
|
hartip_module = prefs_register_protocol(proto_hartip, NULL);
|
|
prefs_register_bool_preference(hartip_module, "desegment",
|
|
"Desegment all HART-IP messages spanning multiple TCP segments",
|
|
"Whether the HART-IP dissector should desegment all messages spanning multiple TCP segments",
|
|
&hartip_desegment);
|
|
|
|
hartip_tap = register_tap("hart_ip");
|
|
}
|
|
|
|
void
|
|
proto_reg_handoff_hartip(void)
|
|
{
|
|
hartip_tcp_handle = create_dissector_handle(dissect_hartip_tcp, proto_hartip);
|
|
hartip_udp_handle = create_dissector_handle(dissect_hartip_udp, proto_hartip);
|
|
dissector_add_uint_with_preference("udp.port", HARTIP_PORT, hartip_udp_handle);
|
|
dissector_add_uint_with_preference("tcp.port", HARTIP_PORT, hartip_tcp_handle);
|
|
|
|
stats_tree_register("hart_ip", "hart_ip", "HART-IP", 0,
|
|
hartip_stats_tree_packet, hartip_stats_tree_init, NULL);
|
|
}
|
|
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 2
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=2 tabstop=8 expandtab:
|
|
* :indentSize=2:tabSize=8:noTabs=true:
|
|
*/
|
|
|