2 * Routines for HART-IP packet dissection
3 * Copyright 2012, Bill Schiller <bill.schiller@emerson.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Copied from packet-mbtcp.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/stats_tree.h>
18 #include <epan/expert.h>
19 #include <epan/prefs.h>
20 #include "packet-tcp.h"
22 void proto_register_hartip(void);
23 void proto_reg_handoff_hartip(void);
25 static dissector_handle_t hartip_tcp_handle;
26 static dissector_handle_t hartip_udp_handle;
28 static gboolean hartip_desegment = TRUE;
30 static int proto_hartip = -1;
31 static int hf_hartip_hdr_version = -1;
32 static int hf_hartip_hdr_message_id = -1;
33 static int hf_hartip_hdr_message_type = -1;
34 static int hf_hartip_hdr_status = -1;
35 static int hf_hartip_hdr_transaction_id = -1;
36 static int hf_hartip_hdr_msg_length = -1;
38 static int hf_hartip_data = -1;
39 static int hf_hartip_master_type = -1;
40 static int hf_hartip_inactivity_close_timer = -1;
41 static int hf_hartip_error_code = -1;
43 static int hf_hartip_pt_preambles = -1;
44 static int hf_hartip_pt_delimiter = -1;
45 static int hf_hartip_pt_short_addr = -1;
46 static int hf_hartip_pt_long_addr = -1;
47 static int hf_hartip_pt_command = -1;
48 static int hf_hartip_pt_length = -1;
49 static int hf_hartip_pt_response_code = -1;
50 static int hf_hartip_pt_device_status = -1;
51 static int hf_hartip_pt_payload = -1;
52 static int hf_hartip_pt_checksum = -1;
54 static gint ett_hartip = -1;
55 static gint ett_hartip_hdr = -1;
56 static gint ett_hartip_body = -1;
58 static expert_field ei_hartip_data_none = EI_INIT;
59 static expert_field ei_hartip_data_unexpected = EI_INIT;
61 /* Command 0 response */
62 static int hf_hartip_pt_rsp_expansion_code = -1;
63 static int hf_hartip_pt_rsp_expanded_device_type = -1;
64 static int hf_hartip_pt_rsp_req_min_preambles = -1;
65 static int hf_hartip_pt_rsp_hart_protocol_major_rev = -1;
66 static int hf_hartip_pt_rsp_device_rev = -1;
67 static int hf_hartip_pt_rsp_software_rev = -1;
68 static int hf_hartip_pt_rsp_hardware_rev_physical_signal = -1;
69 static int hf_hartip_pt_rsp_flage = -1;
70 static int hf_hartip_pt_rsp_device_id = -1;
71 static int hf_hartip_pt_rsp_rsp_min_preambles = -1;
72 static int hf_hartip_pt_rsp_max_device_variables = -1;
73 static int hf_hartip_pt_rsp_configuration_change_counter = -1;
74 static int hf_hartip_pt_rsp_extended_device_status = -1;
75 static int hf_hartip_pt_rsp_manufacturer_Identification_code = -1;
76 static int hf_hartip_pt_rsp_private_label = -1;
77 static int hf_hartip_pt_rsp_device_profile = -1;
79 /* Command 2 response */
80 static int hf_hartip_pt_rsp_pv_percent_range = -1;
82 /* Command 3 response */
83 static int hf_hartip_pt_rsp_pv_loop_current = -1;
84 static int hf_hartip_pt_rsp_pv_units = -1;
85 static int hf_hartip_pt_rsp_pv = -1;
86 static int hf_hartip_pt_rsp_sv_units = -1;
87 static int hf_hartip_pt_rsp_sv = -1;
88 static int hf_hartip_pt_rsp_tv_units = -1;
89 static int hf_hartip_pt_rsp_tv = -1;
90 static int hf_hartip_pt_rsp_qv_units = -1;
91 static int hf_hartip_pt_rsp_qv = -1;
93 /* Command 7 response*/
94 static int hf_hartip_pt_rsp_loop_current_mode = -1;
96 /* Command 8 response*/
97 static int hf_hartip_pt_rsp_primary_var_classify = -1;
98 static int hf_hartip_pt_rsp_secondary_var_classify = -1;
99 static int hf_hartip_pt_rsp_tertiary_var_classify = -1;
100 static int hf_hartip_pt_rsp_quaternary_var_classify = -1;
102 /* Command 9 response */
103 static int hf_hartip_pt_rsp_slot0_device_var = -1;
104 static int hf_hartip_pt_rsp_slot0_device_var_classify = -1;
105 static int hf_hartip_pt_rsp_slot0_units = -1;
106 static int hf_hartip_pt_rsp_slot0_device_var_value = -1;
107 static int hf_hartip_pt_rsp_slot0_device_var_status = -1;
109 static int hf_hartip_pt_rsp_slot1_device_var = -1;
110 static int hf_hartip_pt_rsp_slot1_device_var_classify = -1;
111 static int hf_hartip_pt_rsp_slot1_units = -1;
112 static int hf_hartip_pt_rsp_slot1_device_var_value = -1;
113 static int hf_hartip_pt_rsp_slot1_device_var_status = -1;
115 static int hf_hartip_pt_rsp_slot2_device_var = -1;
116 static int hf_hartip_pt_rsp_slot2_device_var_classify = -1;
117 static int hf_hartip_pt_rsp_slot2_units = -1;
118 static int hf_hartip_pt_rsp_slot2_device_var_value = -1;
119 static int hf_hartip_pt_rsp_slot2_device_var_status = -1;
121 static int hf_hartip_pt_rsp_slot3_device_var = -1;
122 static int hf_hartip_pt_rsp_slot3_device_var_classify = -1;
123 static int hf_hartip_pt_rsp_slot3_units = -1;
124 static int hf_hartip_pt_rsp_slot3_device_var_value = -1;
125 static int hf_hartip_pt_rsp_slot3_device_var_status = -1;
127 static int hf_hartip_pt_rsp_slot4_device_var = -1;
128 static int hf_hartip_pt_rsp_slot4_device_var_classify = -1;
129 static int hf_hartip_pt_rsp_slot4_units = -1;
130 static int hf_hartip_pt_rsp_slot4_device_var_value = -1;
131 static int hf_hartip_pt_rsp_slot4_device_var_status = -1;
133 static int hf_hartip_pt_rsp_slot5_device_var = -1;
134 static int hf_hartip_pt_rsp_slot5_device_var_classify = -1;
135 static int hf_hartip_pt_rsp_slot5_units = -1;
136 static int hf_hartip_pt_rsp_slot5_device_var_value = -1;
137 static int hf_hartip_pt_rsp_slot5_device_var_status = -1;
139 static int hf_hartip_pt_rsp_slot6_device_var = -1;
140 static int hf_hartip_pt_rsp_slot6_device_var_classify = -1;
141 static int hf_hartip_pt_rsp_slot6_units = -1;
142 static int hf_hartip_pt_rsp_slot6_device_var_value = -1;
143 static int hf_hartip_pt_rsp_slot6_device_var_status = -1;
145 static int hf_hartip_pt_rsp_slot7_device_var = -1;
146 static int hf_hartip_pt_rsp_slot7_device_var_classify = -1;
147 static int hf_hartip_pt_rsp_slot7_units = -1;
148 static int hf_hartip_pt_rsp_slot7_device_var_value = -1;
149 static int hf_hartip_pt_rsp_slot7_device_var_status = -1;
151 static int hf_hartip_pt_rsp_slot0_timestamp = -1;
153 /* Command 13 response */
154 static int hf_hartip_pt_rsp_packed_descriptor = -1;
155 static int hf_hartip_pt_rsp_day = -1;
156 static int hf_hartip_pt_rsp_month = -1;
157 static int hf_hartip_pt_rsp_year = -1;
159 /* Command 14 response */
160 static int hf_hartip_pt_rsp_transducer_serial_number = -1;
161 static int hf_hartip_pt_rsp_transducer_limit_min_span_units = -1;
162 static int hf_hartip_pt_rsp_upper_transducer_limit = -1;
163 static int hf_hartip_pt_rsp_lower_transducer_limit = -1;
164 static int hf_hartip_pt_rsp_minimum_span = -1;
166 /* Command 15 response */
167 static int hf_hartip_pt_rsp_pv_alarm_selection_code = -1;
168 static int hf_hartip_pt_rsp_pv_transfer_function_code = -1;
169 static int hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units = -1;
170 static int hf_hartip_pt_rsp_pv_upper_range_value = -1;
171 static int hf_hartip_pt_rsp_pv_lower_range_value = -1;
172 static int hf_hartip_pt_rsp_pv_damping_value = -1;
173 static int hf_hartip_pt_rsp_write_protect_code = -1;
174 static int hf_hartip_pt_rsp_reserved = -1;
175 static int hf_hartip_pt_rsp_pv_analog_channel_flags = -1;
177 /* Command 16 and 19 response */
178 static int hf_hartip_pt_rsp_final_assembly_number = -1;
181 static int hf_hartip_pt_rsp_tag = -1;
183 /* response Message */
184 static int hf_hartip_pt_rsp_message = -1;
186 /* Command 48 response */
187 static int hf_hartip_pt_rsp_device_sp_status = -1;
188 static int hf_hartip_pt_rsp_device_op_mode = -1;
189 static int hf_hartip_pt_rsp_standardized_status_0 = -1;
190 static int hf_hartip_pt_rsp_standardized_status_1 = -1;
191 static int hf_hartip_pt_rsp_analog_channel_saturated = -1;
192 static int hf_hartip_pt_rsp_standardized_status_2 = -1;
193 static int hf_hartip_pt_rsp_standardized_status_3 = -1;
194 static int hf_hartip_pt_rsp_analog_channel_fixed = -1;
196 /* Command 77 response */
197 static int hf_hartip_pt_rsp_io_card = -1;
198 static int hf_hartip_pt_rsp_channel = -1;
199 static int hf_hartip_pt_rsp_embedded_cmd_delimiter = -1;
200 static int hf_hartip_pt_rsp_poll_address = -1;
201 static int hf_hartip_pt_rsp_embedded_cmd = -1;
203 /* Command 31 and 178 response */
204 static int hf_hartip_pt_rsp_number_of_commands = -1;
205 static int hf_hartip_pt_rsp_command_number = -1;
206 static int hf_hartip_pt_rsp_command_byte_count = -1;
208 /* Command 31, 77 and 178 response */
209 static int hf_hartip_pt_rsp_data = -1;
211 /*Command 203 response*/
212 static int hf_hartip_pt_rsp_index_of_first_discrete_var = -1;
213 static int hf_hartip_pt_rsp_number_of_discrete_vars = -1;
214 static int hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change = -1;
216 static int hf_hartip_pt_rsp_slot0_discrete_var_state = -1;
217 static int hf_hartip_pt_rsp_slot0_discrete_var_status = -1;
219 static int hf_hartip_pt_rsp_slot1_discrete_var_state = -1;
220 static int hf_hartip_pt_rsp_slot1_discrete_var_status = -1;
222 static int hf_hartip_pt_rsp_slot2_discrete_var_state = -1;
223 static int hf_hartip_pt_rsp_slot2_discrete_var_status = -1;
225 static int hf_hartip_pt_rsp_slot3_discrete_var_state = -1;
226 static int hf_hartip_pt_rsp_slot3_discrete_var_status = -1;
228 static int hf_hartip_pt_rsp_slot4_discrete_var_state = -1;
229 static int hf_hartip_pt_rsp_slot4_discrete_var_status = -1;
231 static int hf_hartip_pt_rsp_slot5_discrete_var_state = -1;
232 static int hf_hartip_pt_rsp_slot5_discrete_var_status = -1;
234 #define HARTIP_HEADER_LENGTH 8
235 #define HARTIP_PORT 5094
238 typedef struct _hartip_hdr {
243 guint16 transaction_id;
248 #define SESSION_INITIATE_ID 0
249 #define SESSION_CLOSE_ID 1
250 #define KEEP_ALIVE_ID 2
251 #define PASS_THROUGH_ID 3
254 #define REQUEST_MSG_TYPE 0
255 #define RESPONSE_MSG_TYPE 1
256 #define PUBLISH_MSG_TYPE 2
257 #define ERROR_MSG_TYPE 3
258 #define NAK_MSG_TYPE 15
260 static const value_string hartip_message_id_values[] = {
261 { SESSION_INITIATE_ID, "Session Initiate" },
262 { SESSION_CLOSE_ID, "Session Close" },
263 { KEEP_ALIVE_ID, "Keep Alive" },
264 { PASS_THROUGH_ID, "Pass Through" },
268 static const value_string hartip_message_type_values[] = {
269 { REQUEST_MSG_TYPE, "Request" },
270 { RESPONSE_MSG_TYPE, "Response" },
271 { PUBLISH_MSG_TYPE, "Publish" },
272 { ERROR_MSG_TYPE, "Error" },
273 { NAK_MSG_TYPE, "Error" },
278 #define SECONDARY_MASTER_TYPE 0
279 #define PRIMARY_MASTER_TYPE 1
281 static const value_string hartip_master_type_values[] = {
282 { SECONDARY_MASTER_TYPE, "Secondary Host" },
283 { PRIMARY_MASTER_TYPE, "Primary Host" },
288 #define SESSION_CLOSED_ERROR 0
289 #define PRIMARY_SESSION_UNAVAILABLE_ERROR 1
290 #define SERVICE_UNAVAILABLE_ERROR 2
292 static const value_string hartip_error_code_values[] = {
293 { SESSION_CLOSED_ERROR, "Session closed" },
294 { PRIMARY_SESSION_UNAVAILABLE_ERROR, "Primary session unavailable" },
295 { SERVICE_UNAVAILABLE_ERROR, "Service unavailable" },
299 /* Handle for statistics tap. */
300 static int hartip_tap = -1;
302 /* Structure used for passing data for statistics processing. */
303 typedef struct _hartip_tap_info {
308 /* Names of items in statistics tree. */
309 static const gchar* st_str_packets = "Total HART_IP Packets";
310 static const gchar* st_str_requests = "Request Packets";
311 static const gchar* st_str_responses = "Response Packets";
312 static const gchar* st_str_publish = "Publish Packets";
313 static const gchar* st_str_errors = "Error Packets";
315 /* Handles of items in statistics tree. */
316 static int st_node_packets = -1;
317 static int st_node_requests = -1;
318 static int st_node_responses = -1;
319 static int st_node_publish = -1;
320 static int st_node_errors = -1;
323 hartip_stats_tree_init(stats_tree* st)
325 st_node_packets = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, TRUE);
326 st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
327 st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, STAT_DT_INT, TRUE);
328 st_node_publish = stats_tree_create_node(st, st_str_publish, st_node_packets, STAT_DT_INT, TRUE);
329 st_node_errors = stats_tree_create_node(st, st_str_errors, st_node_packets, STAT_DT_INT, TRUE);
332 static tap_packet_status
333 hartip_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_,
334 epan_dissect_t* edt _U_, const void* p)
336 const hartip_tap_info *tapinfo = (const hartip_tap_info *)p;
337 const gchar *message_type_node_str, *message_id_node_str;
338 int message_type_node;
340 switch (tapinfo->message_type) {
341 case REQUEST_MSG_TYPE:
342 message_type_node_str = st_str_requests;
343 message_type_node = st_node_requests;
345 case RESPONSE_MSG_TYPE:
346 message_type_node_str = st_str_responses;
347 message_type_node = st_node_responses;
349 case PUBLISH_MSG_TYPE:
350 message_type_node_str = st_str_publish;
351 message_type_node = st_node_publish;
355 message_type_node_str = st_str_errors;
356 message_type_node = st_node_errors;
359 return TAP_PACKET_DONT_REDRAW; /* Don't want to track invalid messages for now. */
362 message_id_node_str = val_to_str(tapinfo->message_id,
363 hartip_message_id_values,
364 "Unknown message %d");
366 tick_stat_node(st, st_str_packets, 0, FALSE);
367 tick_stat_node(st, message_type_node_str, st_node_packets, FALSE);
368 tick_stat_node(st, message_id_node_str, message_type_node, FALSE);
370 return TAP_PACKET_REDRAW;
374 dissect_empty_body(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb,
375 gint offset, gint bodylen)
379 ti = proto_tree_add_item(tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
381 expert_add_info(pinfo, ti, &ei_hartip_data_none);
383 expert_add_info(pinfo, ti, &ei_hartip_data_unexpected);
389 dissect_session_init(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
393 proto_tree_add_item(body_tree, hf_hartip_master_type, tvb, offset, 1, ENC_BIG_ENDIAN);
396 proto_tree_add_item(body_tree, hf_hartip_inactivity_close_timer, tvb, offset, 4, ENC_BIG_ENDIAN);
398 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
405 dissect_error(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
408 proto_tree_add_item(body_tree, hf_hartip_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
410 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
417 dissect_session_close(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
418 gint offset, gint bodylen)
420 return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
424 dissect_keep_alive(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
425 gint offset, gint bodylen)
427 return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
431 dissect_byte(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
433 proto_tree_add_item(tree, hf, tvb, offset, 1, ENC_BIG_ENDIAN);
438 dissect_short(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
440 proto_tree_add_item(tree, hf, tvb, offset, 2, ENC_BIG_ENDIAN);
445 dissect_float(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
447 proto_tree_add_item(tree, hf, tvb, offset, 4, ENC_BIG_ENDIAN);
452 dissect_packAscii(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset, int len)
456 gushort usMaxGroups; /* Number of 4 byte groups to pack. */
464 tmp = (guint8 *)wmem_alloc0(wmem_packet_scope(), len);
465 tvb_memcpy(tvb, tmp, offset, len);
467 /* Maximum possible unpacked length = (len / 3) * 4 */
468 str = (char *)wmem_alloc(wmem_packet_scope(), ((len / 3) * 4)+1);
471 usMaxGroups = (gushort)(len / 3);
472 for (usGroupCnt = 0; usGroupCnt < usMaxGroups; usGroupCnt++) {
474 * First unpack 3 bytes into a group of 4 bytes, clearing bits 6 & 7.
476 buf[0] = (gushort)(tmp[iIndex] >> 2);
477 buf[1] = (gushort)(((tmp[iIndex] << 4) & 0x30) | (tmp[iIndex + 1] >> 4));
478 buf[2] = (gushort)(((tmp[iIndex + 1] << 2) & 0x3C) | (tmp[iIndex + 2] >> 6));
479 buf[3] = (gushort)(tmp[iIndex + 2] & 0x3F);
483 * Now transfer to unpacked area, setting bit 6 to complement of bit 5.
485 for (usIdx = 0; usIdx < 4; usIdx++) {
486 usMask = (gushort)(((buf[usIdx] & 0x20) << 1) ^ 0x40);
487 DISSECTOR_ASSERT(i < 256);
488 str[i++] = (gchar)(buf[usIdx] | usMask);
493 proto_tree_add_string(tree, hf, tvb, offset, len, str);
499 dissect_timestamp(proto_tree *tree, int hf, const char *name, int len,
500 tvbuff_t *tvb, gint offset)
509 ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA);
510 t = tvb_get_ntohl(tvb, offset);
519 hrs = (guint)(t / 60);
522 proto_item_set_text(ti, "%s: %02d:%02d:%02d.%03d", name, hrs, mins, secs, ms);
527 dissect_cmd0(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
530 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_expansion_code, tvb, offset);
531 offset += dissect_short(body_tree, hf_hartip_pt_rsp_expanded_device_type, tvb, offset);
532 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_req_min_preambles, tvb, offset);
533 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_hart_protocol_major_rev, tvb, offset);
534 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_device_rev, tvb, offset);
535 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_software_rev, tvb, offset);
536 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_hardware_rev_physical_signal, tvb, offset);
537 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_flage, tvb, offset);
538 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_id, tvb, offset, 3, ENC_NA);
542 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_rsp_min_preambles, tvb, offset);
543 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_max_device_variables, tvb, offset);
544 offset += dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter, tvb, offset);
545 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
549 offset += dissect_short(body_tree, hf_hartip_pt_rsp_manufacturer_Identification_code, tvb, offset);
553 offset += dissect_short(body_tree, hf_hartip_pt_rsp_private_label, tvb, offset);
554 /*offset += */dissect_byte(body_tree, hf_hartip_pt_rsp_device_profile, tvb, offset);
564 dissect_cmd1(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
567 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_units, tvb, offset);
568 /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv, tvb, offset);
576 dissect_cmd2(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
579 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
580 /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv_percent_range, tvb, offset);
588 dissect_cmd3(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
591 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
592 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_units, tvb, offset);
593 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv, tvb, offset);
594 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_sv_units, tvb, offset);
595 offset += dissect_float(body_tree, hf_hartip_pt_rsp_sv, tvb, offset);
596 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_tv_units, tvb, offset);
597 offset += dissect_float(body_tree, hf_hartip_pt_rsp_tv, tvb, offset);
598 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_qv_units, tvb, offset);
599 /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_qv, tvb, offset);
608 dissect_cmd7(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
611 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address, tvb, offset);
612 dissect_byte(body_tree, hf_hartip_pt_rsp_loop_current_mode, tvb, offset);
620 dissect_cmd8(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
623 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_primary_var_classify, tvb, offset);
624 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_secondary_var_classify, tvb, offset);
625 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_tertiary_var_classify, tvb, offset);
626 dissect_byte(body_tree, hf_hartip_pt_rsp_quaternary_var_classify, tvb, offset);
634 dissect_cmd9(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
637 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
638 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var, tvb, offset);
639 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var_classify, tvb, offset);
640 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_units, tvb, offset);
641 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot0_device_var_value, tvb, offset);
642 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var_status, tvb, offset);
645 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var, tvb, offset);
646 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var_classify, tvb, offset);
647 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_units, tvb, offset);
648 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot1_device_var_value, tvb, offset);
649 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var_status, tvb, offset);
653 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var, tvb, offset);
654 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var_classify, tvb, offset);
655 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_units, tvb, offset);
656 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot2_device_var_value, tvb, offset);
657 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var_status, tvb, offset);
661 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var, tvb, offset);
662 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var_classify, tvb, offset);
663 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_units, tvb, offset);
664 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot3_device_var_value, tvb, offset);
665 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var_status, tvb, offset);
669 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var, tvb, offset);
670 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var_classify, tvb, offset);
671 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_units, tvb, offset);
672 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot4_device_var_value, tvb, offset);
673 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_device_var_status, tvb, offset);
677 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var, tvb, offset);
678 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var_classify, tvb, offset);
679 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_units, tvb, offset);
680 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot5_device_var_value, tvb, offset);
681 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_device_var_status, tvb, offset);
685 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var, tvb, offset);
686 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var_classify, tvb, offset);
687 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_units, tvb, offset);
688 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot6_device_var_value, tvb, offset);
689 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot6_device_var_status, tvb, offset);
693 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var, tvb, offset);
694 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var_classify, tvb, offset);
695 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_units, tvb, offset);
696 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot7_device_var_value, tvb, offset);
697 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot7_device_var_status, tvb, offset);
700 dissect_timestamp(body_tree, hf_hartip_pt_rsp_slot0_timestamp, "Slot0 Data TimeStamp", 4, tvb, offset);
709 dissect_cmd13(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
712 offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 6);
713 offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_packed_descriptor, tvb, offset, 12);
714 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_day, tvb, offset);
715 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_month, tvb, offset);
716 /*offset += */dissect_byte(body_tree, hf_hartip_pt_rsp_year, tvb, offset);
725 dissect_cmd14(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
728 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_transducer_serial_number, tvb, offset, 3, ENC_NA);
730 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_transducer_limit_min_span_units, tvb, offset);
731 offset += dissect_float(body_tree, hf_hartip_pt_rsp_upper_transducer_limit, tvb, offset);
732 offset += dissect_float(body_tree, hf_hartip_pt_rsp_lower_transducer_limit, tvb, offset);
733 dissect_float(body_tree, hf_hartip_pt_rsp_minimum_span, tvb, offset);
742 dissect_cmd15(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
745 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_alarm_selection_code, tvb, offset);
746 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_transfer_function_code, tvb, offset);
747 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units, tvb, offset);
748 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_upper_range_value, tvb, offset);
749 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_lower_range_value, tvb, offset);
750 offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_damping_value, tvb, offset);
751 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_write_protect_code, tvb, offset);
752 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_reserved, tvb, offset);
753 dissect_byte(body_tree, hf_hartip_pt_rsp_pv_analog_channel_flags, tvb, offset);
762 dissect_cmd16(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
765 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_final_assembly_number, tvb, offset, 3, ENC_NA);
774 dissect_cmd33(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
777 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_device_var, tvb, offset);
778 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_units, tvb, offset);
779 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot0_device_var_value, tvb, offset);
782 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_device_var, tvb, offset);
783 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_units, tvb, offset);
784 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot1_device_var_value, tvb, offset);
788 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_device_var, tvb, offset);
789 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_units, tvb, offset);
790 offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot2_device_var_value, tvb, offset);
794 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_device_var, tvb, offset);
795 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_units, tvb, offset);
796 dissect_float(body_tree, hf_hartip_pt_rsp_slot3_device_var_value, tvb, offset);
806 dissect_cmd38(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
809 dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter, tvb, offset);
818 dissect_cmd48(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
821 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 6, ENC_NA);
825 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
826 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_device_op_mode, tvb, offset);
827 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_0, tvb, offset);
831 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_1, tvb, offset);
832 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_saturated, tvb, offset);
833 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_2, tvb, offset);
834 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_3, tvb, offset);
838 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_fixed, tvb, offset);
842 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 11, ENC_NA);
852 dissect_cmd77(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
855 gint length = bodylen;
858 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_io_card, tvb, offset);
859 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_channel, tvb, offset);
860 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd_delimiter, tvb, offset);
861 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address, tvb, offset);
862 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd, tvb, offset);
864 byte_count = tvb_get_guint8(tvb, offset);
865 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
869 if ((byte_count >= 2) && (length >= 2) && (byte_count <= length)) {
870 offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
871 offset += dissect_byte(body_tree, hf_hartip_pt_device_status, tvb, offset);
875 if ((byte_count > 0) && (length > 0) && (byte_count <= length)) {
876 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
888 dissect_cmd178(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
891 guint8 number_of_cmds;
892 guint8 cmd_byte_count;
893 gint length = bodylen;
898 number_of_cmds = tvb_get_guint8(tvb, offset);
899 proto_tree_add_uint(body_tree, hf_hartip_pt_rsp_number_of_commands, tvb, offset, 1, number_of_cmds);
903 for (i = 0; i < number_of_cmds; i++)
907 cmd = tvb_get_ntohs(tvb, offset);
908 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
912 cmd_byte_count = tvb_get_guint8(tvb, offset);
913 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
917 offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
921 if ((cmd_byte_count > 0) && (length > 0) && (cmd_byte_count <= length))
926 result = dissect_cmd3(body_tree, tvb, offset, cmd_byte_count);
929 result = dissect_cmd9(body_tree, tvb, offset, cmd_byte_count);
932 result = dissect_cmd48(body_tree, tvb, offset, cmd_byte_count);
940 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
941 cmd_byte_count, ENC_NA);
944 offset += cmd_byte_count;
945 length -= cmd_byte_count;
959 dissect_cmd203(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
962 offset += dissect_short(body_tree, hf_hartip_pt_rsp_index_of_first_discrete_var, tvb, offset);
963 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_number_of_discrete_vars, tvb, offset);
964 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status, tvb, offset);
965 dissect_timestamp(body_tree, hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
966 "TimeStamp for Most Recent Discrete Change", 4, tvb, offset);
971 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_state, tvb, offset);
972 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_status, tvb, offset);
977 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_state, tvb, offset);
978 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_status, tvb, offset);
983 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_state, tvb, offset);
984 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_status, tvb, offset);
989 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_state, tvb, offset);
990 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_status, tvb, offset);
995 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_state, tvb, offset);
996 offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_status, tvb, offset);
1001 offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_state, tvb, offset);
1002 dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_status, tvb, offset);
1012 dissect_cmd31(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
1014 gint length = bodylen;
1019 cmd = tvb_get_ntohs(tvb, offset);
1020 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
1028 result = dissect_cmd203(body_tree, tvb, offset, length);
1033 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
1045 dissect_parse_hart_cmds(proto_tree *body_tree, tvbuff_t *tvb, guint8 cmd,
1046 gint offset, gint bodylen)
1053 return dissect_cmd0(body_tree, tvb, offset, bodylen);
1055 return dissect_cmd1(body_tree, tvb, offset, bodylen);
1057 return dissect_cmd2(body_tree, tvb, offset, bodylen);
1059 return dissect_cmd3(body_tree, tvb, offset, bodylen);
1062 return dissect_cmd7(body_tree, tvb, offset, bodylen);
1064 return dissect_cmd8(body_tree, tvb, offset, bodylen);
1066 return dissect_cmd9(body_tree, tvb, offset, bodylen);
1070 return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, tvb, offset, 24);
1074 return dissect_cmd13(body_tree, tvb, offset, bodylen);
1076 return dissect_cmd14(body_tree, tvb, offset, bodylen);
1078 return dissect_cmd15(body_tree, tvb, offset, bodylen);
1081 return dissect_cmd16(body_tree, tvb, offset, bodylen);
1084 if (bodylen >= 32) {
1085 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 32,
1091 return dissect_cmd31(body_tree, tvb, offset, bodylen);
1093 return dissect_cmd33(body_tree, tvb, offset, bodylen);
1095 return dissect_cmd38(body_tree, tvb, offset, bodylen);
1097 return dissect_cmd48(body_tree, tvb, offset, bodylen);
1099 return dissect_cmd77(body_tree, tvb, offset, bodylen);
1101 return dissect_cmd178(body_tree, tvb, offset, bodylen);
1103 return dissect_cmd203(body_tree, tvb, offset, bodylen);
1110 dissect_pass_through(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
1115 const char *frame_type_str;
1117 gint length = bodylen;
1120 gint num_preambles = 0;
1124 /* find number of preambles */
1125 while (length > num_preambles) {
1126 delimiter = tvb_get_guint8(tvb, offset + num_preambles);
1127 if (delimiter != 0xFF)
1133 if (num_preambles > 0) {
1134 proto_tree_add_item(body_tree, hf_hartip_pt_preambles, tvb, offset,
1135 num_preambles, ENC_NA);
1136 offset += num_preambles;
1137 length -= num_preambles;
1141 delimiter = tvb_get_guint8(tvb, offset);
1142 ti = proto_tree_add_uint(body_tree, hf_hartip_pt_delimiter, tvb, offset, 1,
1147 if ((delimiter & 0x7) == 2) {
1148 frame_type_str = "STX";
1149 } else if ((delimiter & 0x7) == 6) {
1150 frame_type_str = "ACK";
1152 } else if ((delimiter & 0x7) == 1) {
1153 frame_type_str = "PUB";
1156 frame_type_str = "UNK";
1159 if ((delimiter & 0x80) == 0) {
1161 proto_item_set_text(ti, "Short Address, Frame Type: %s", frame_type_str);
1163 proto_item_set_text(ti, "Frame Type: %s", frame_type_str);
1167 if (is_short == 1) {
1169 short_addr = tvb_get_guint8(tvb, offset);
1170 short_addr = short_addr & 0x3F;
1171 proto_tree_add_uint(body_tree, hf_hartip_pt_short_addr, tvb, offset, 1,
1178 proto_tree_add_item(body_tree, hf_hartip_pt_long_addr, tvb, offset, 5, ENC_NA);
1181 } else if (length > 0) {
1182 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, length, ENC_NA);
1188 cmd = tvb_get_guint8(tvb, offset);
1189 proto_tree_add_item(body_tree, hf_hartip_pt_command, tvb, offset, 1, ENC_BIG_ENDIAN);
1194 proto_tree_add_item(body_tree, hf_hartip_pt_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1201 proto_tree_add_item(body_tree, hf_hartip_pt_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1206 proto_tree_add_item(body_tree, hf_hartip_pt_device_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1213 result = dissect_parse_hart_cmds(body_tree, tvb, cmd, offset, (length - 1));
1215 proto_tree_add_item(body_tree, hf_hartip_pt_payload, tvb, offset,
1216 (length - 1), ENC_NA);
1218 offset += (length - 1);
1222 proto_tree_add_checksum(body_tree, tvb, offset, hf_hartip_pt_checksum, -1, NULL, NULL, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1229 hartip_set_conversation(packet_info *pinfo)
1231 conversation_t *conversation = NULL;
1233 if (!pinfo->fd->visited && (pinfo->ptype == PT_UDP)) {
1235 * This function is called for a session initiate send over UDP.
1236 * The session initiate is sent to the server on port HARTIP_PORT.
1237 * The server then responds from a different port. All subsequent
1238 * communication for the session between the client and server
1239 * uses the new server port and the original client port.
1241 * A new conversation is created here and this dissector is set to
1242 * be used for it. This allows the packets to be dissected properly
1243 * for this protocol.
1245 conversation = find_conversation(pinfo->num,
1246 &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1247 pinfo->srcport, 0, NO_PORT_B);
1248 if( (conversation == NULL) ||
1249 (conversation_get_dissector(conversation, pinfo->num) != hartip_udp_handle) ) {
1250 conversation = conversation_new(pinfo->num,
1251 &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1252 pinfo->srcport, 0, NO_PORT2);
1253 conversation_set_dissector(conversation, hartip_udp_handle);
1259 dissect_hartip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1262 proto_tree *hartip_tree, *hdr_tree, *body_tree;
1263 proto_item *hart_item;
1265 guint8 message_type, message_id;
1266 guint16 transaction_id, length;
1267 const char *msg_id_str, *msg_type_str;
1268 hartip_tap_info *tapinfo;
1270 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HART_IP");
1271 col_clear(pinfo->cinfo, COL_INFO);
1273 length = tvb_get_ntohs(tvb, offset+6);
1275 hart_item = proto_tree_add_item(tree, proto_hartip, tvb, 0, length, ENC_NA);
1276 hartip_tree = proto_item_add_subtree(hart_item, ett_hartip);
1278 hdr_tree = proto_tree_add_subtree(hartip_tree, tvb, offset, HARTIP_HEADER_LENGTH,
1279 ett_hartip_hdr, NULL, "HART_IP Header");
1281 proto_tree_add_item(hdr_tree, hf_hartip_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1284 message_type = tvb_get_guint8(tvb, offset);
1285 msg_type_str = val_to_str(message_type, hartip_message_type_values, "Unknown message type %d");
1286 proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1289 message_id = tvb_get_guint8(tvb, offset);
1290 msg_id_str = val_to_str(message_id, hartip_message_id_values, "Unknown message %d");
1291 proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1294 /* Setup statistics for tap. */
1295 tapinfo = wmem_new(wmem_packet_scope(), hartip_tap_info);
1296 tapinfo->message_type = message_type;
1297 tapinfo->message_id = message_id;
1298 tap_queue_packet(hartip_tap, pinfo, tapinfo);
1300 if (message_id == SESSION_INITIATE_ID) {
1301 hartip_set_conversation(pinfo);
1304 proto_tree_add_item(hdr_tree, hf_hartip_hdr_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1307 transaction_id = tvb_get_ntohs(tvb, offset);
1308 proto_tree_add_item(hdr_tree, hf_hartip_hdr_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1311 proto_item_append_text(hart_item, ", %s %s, Sequence Number %d", msg_id_str,
1312 msg_type_str, transaction_id);
1314 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ",
1315 "%s %s, Sequence Number %d",
1316 msg_id_str, msg_type_str, transaction_id);
1317 col_set_fence(pinfo->cinfo, COL_INFO);
1319 proto_tree_add_item(hdr_tree, hf_hartip_hdr_msg_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1322 if (length < HARTIP_HEADER_LENGTH)
1323 return tvb_reported_length(tvb);
1324 bodylen = length - HARTIP_HEADER_LENGTH;
1326 /* add body elements. */
1327 body_tree = proto_tree_add_subtree_format(hartip_tree, tvb, offset, bodylen,
1328 ett_hartip_body, NULL,
1329 "HART_IP Body, %s, %s", msg_id_str, msg_type_str);
1331 if ((message_type == ERROR_MSG_TYPE) ||
1332 (message_type == NAK_MSG_TYPE)) {
1333 offset += dissect_error(body_tree, tvb, offset, bodylen);
1335 /* Dissect the various HARTIP messages. */
1336 switch(message_id) {
1337 case SESSION_INITIATE_ID:
1338 offset += dissect_session_init(body_tree, tvb, offset, bodylen);
1340 case SESSION_CLOSE_ID:
1341 offset += dissect_session_close(body_tree, pinfo, tvb, offset, bodylen);
1344 offset += dissect_keep_alive(body_tree, pinfo, tvb, offset, bodylen);
1346 case PASS_THROUGH_ID:
1347 offset += dissect_pass_through(body_tree, tvb, offset, bodylen);
1350 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
1360 get_dissect_hartip_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1361 int offset, void *data _U_)
1363 return tvb_get_ntohs(tvb, offset+6);
1367 dissect_hartip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1369 return dissect_hartip_common(tvb, pinfo, tree, 0);
1373 dissect_hartip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1376 /* Simple hueristic check*/
1377 const gchar * msg_str = try_val_to_str(tvb_get_guint8(tvb, 1), hartip_message_type_values);
1382 msg_str = try_val_to_str(tvb_get_guint8(tvb, 2), hartip_message_id_values);
1387 tcp_dissect_pdus(tvb, pinfo, tree, hartip_desegment, HARTIP_HEADER_LENGTH,
1388 get_dissect_hartip_len, dissect_hartip_pdu, data);
1389 return tvb_reported_length(tvb);
1393 dissect_hartip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1398 /* Simple hueristic check*/
1399 const gchar * msg_str = try_val_to_str(tvb_get_guint8(tvb, 1), hartip_message_type_values);
1404 msg_str = try_val_to_str(tvb_get_guint8(tvb, 2), hartip_message_id_values);
1409 while (tvb_reported_length_remaining(tvb, offset) >= HARTIP_HEADER_LENGTH)
1410 offset += dissect_hartip_common(tvb, pinfo, tree, offset);
1416 proto_register_hartip(void)
1418 static hf_register_info hf[] = {
1419 /* HARTIP header elements. */
1420 { &hf_hartip_hdr_version,
1421 { "Version", "hart_ip.version",
1422 FT_UINT8, BASE_DEC, NULL, 0x0,
1423 "HART_IP version number", HFILL }
1425 { &hf_hartip_hdr_message_type,
1426 { "Message Type", "hart_ip.message_type",
1427 FT_UINT8, BASE_DEC, VALS(hartip_message_type_values), 0,
1428 "HART_IP message type", HFILL }
1430 { &hf_hartip_hdr_message_id,
1431 { "Message ID", "hart_ip.message_id",
1432 FT_UINT8, BASE_DEC, VALS(hartip_message_id_values), 0,
1433 "HART_IP message id", HFILL }
1435 { &hf_hartip_hdr_status,
1436 { "Status", "hart_ip.status",
1437 FT_UINT8, BASE_DEC, NULL, 0x0,
1438 "HART_IP status field", HFILL }
1440 { &hf_hartip_hdr_transaction_id,
1441 { "Sequence Number", "hart_ip.transaction_id",
1442 FT_UINT16, BASE_DEC, NULL, 0x0,
1443 "HART_IP Sequence Number", HFILL }
1445 { &hf_hartip_hdr_msg_length,
1446 { "Message Length", "hart_ip.msg_length",
1447 FT_UINT16, BASE_DEC, NULL, 0x0,
1448 "HART_IP Message Length", HFILL }
1451 /* HARTIP Body elements */
1453 { "Message Data", "hart_ip.data",
1454 FT_BYTES, BASE_NONE, NULL, 0x0,
1455 "HART_IP Message Data", HFILL }
1457 { &hf_hartip_master_type,
1458 { "Host Type", "hart_ip.session_init.master_type",
1459 FT_UINT8, BASE_DEC, VALS(hartip_master_type_values), 0xFF,
1460 "Session Host Type", HFILL }
1462 { &hf_hartip_inactivity_close_timer,
1463 { "Inactivity Close Timer", "hart_ip.session_init.inactivity_close_timer",
1464 FT_UINT32, BASE_DEC, NULL, 0x0,
1465 "Session Inactivity Close Timer", HFILL }
1467 { &hf_hartip_error_code,
1468 { "Error", "hart_ip.error.error_code",
1469 FT_UINT8, BASE_DEC, VALS(hartip_error_code_values), 0xFF,
1470 "Error Code", HFILL }
1473 /* HARTIP Pass-through commads. */
1474 { &hf_hartip_pt_preambles,
1475 { "Preambles", "hart_ip.pt.preambles",
1476 FT_BYTES, BASE_NONE, NULL, 0x0,
1477 "Pass Through Preambles", HFILL }
1479 { &hf_hartip_pt_delimiter,
1480 { "Delimter", "hart_ip.pt.delimter",
1481 FT_UINT8, BASE_HEX, NULL, 0x0,
1482 "Pass Through Delimiter", HFILL }
1484 { &hf_hartip_pt_short_addr,
1485 { "Short Address", "hart_ip.pt.short_addr",
1486 FT_UINT8, BASE_DEC, NULL, 0x0,
1487 "Pass Through Short Address", HFILL }
1489 { &hf_hartip_pt_long_addr,
1490 { "Long Address", "hart_ip.pt.long_address",
1491 FT_BYTES, BASE_NONE, NULL, 0x0,
1492 "Pass Through Long Address", HFILL }
1494 { &hf_hartip_pt_command,
1495 { "Command", "hart_ip.pt.command",
1496 FT_UINT8, BASE_DEC, NULL, 0x0,
1497 "Pass Through Command", HFILL }
1499 { &hf_hartip_pt_length,
1500 { "Length", "hart_ip.pt.length",
1501 FT_UINT8, BASE_DEC, NULL, 0x0,
1502 "Pass Through Length", HFILL }
1504 { &hf_hartip_pt_response_code,
1505 { "Response Code", "hart_ip.pt.response_code",
1506 FT_UINT8, BASE_DEC, NULL, 0x0,
1507 "Pass Through Response Code", HFILL }
1509 { &hf_hartip_pt_device_status,
1510 { "Device Status", "hart_ip.pt.device_status",
1511 FT_UINT8, BASE_HEX, NULL, 0x0,
1512 "Pass Through Device Status", HFILL }
1514 { &hf_hartip_pt_payload,
1515 { "Payload", "hart_ip.pt.payload",
1516 FT_BYTES, BASE_NONE, NULL, 0x0,
1517 "Pass Through Payload", HFILL }
1519 { &hf_hartip_pt_checksum,
1520 { "Checksum", "hart_ip.pt.checksum",
1521 FT_UINT8, BASE_HEX, NULL, 0x0,
1522 "Pass Through Checksum", HFILL }
1525 /* add fields for universal commands. */
1527 { &hf_hartip_pt_rsp_expansion_code,
1528 { "Expansion Code", "hart_ip.pt.rsp.expansion_code",
1529 FT_UINT8, BASE_DEC, NULL, 0x0,
1532 { &hf_hartip_pt_rsp_expanded_device_type,
1533 { "Expanded Device Type", "hart_ip.pt.rsp.expanded_device_type",
1534 FT_UINT16, BASE_HEX, NULL, 0x0,
1537 { &hf_hartip_pt_rsp_req_min_preambles,
1538 { "Minimum Number of Request Preambles", "hart_ip.pt.rsp.req_min_preambles",
1539 FT_UINT8, BASE_DEC, NULL, 0x0,
1542 { &hf_hartip_pt_rsp_hart_protocol_major_rev,
1543 { "HART Universal Revision", "hart_ip.pt.rsp.hart_univ_rev",
1544 FT_UINT8, BASE_DEC, NULL, 0x0,
1547 { &hf_hartip_pt_rsp_device_rev,
1548 { "Device Revision", "hart_ip.pt.rsp.device_rev",
1549 FT_UINT8, BASE_DEC, NULL, 0x0,
1552 { &hf_hartip_pt_rsp_software_rev,
1553 { "Device Software Revision", "hart_ip.pt.rsp.software_rev",
1554 FT_UINT8, BASE_DEC, NULL, 0x0,
1557 { &hf_hartip_pt_rsp_hardware_rev_physical_signal,
1558 { "Hardware Rev and Physical Signaling", "hart_ip.pt.rsp.hardrev_and_physical_signal",
1559 FT_UINT8, BASE_HEX, NULL, 0x0,
1562 { &hf_hartip_pt_rsp_flage,
1563 { "Flags", "hart_ip.pt.rsp.flags",
1564 FT_UINT8, BASE_HEX, NULL, 0x0,
1567 { &hf_hartip_pt_rsp_device_id,
1568 { "Device ID", "hart_ip.pt.rsp.device_id",
1569 FT_BYTES, BASE_NONE, NULL, 0x0,
1572 { &hf_hartip_pt_rsp_rsp_min_preambles,
1573 { "Minimum Number of Response Preambles", "hart_ip.pt.rsp.rsp_min_preambles",
1574 FT_UINT8, BASE_DEC, NULL, 0x0,
1577 { &hf_hartip_pt_rsp_max_device_variables,
1578 { "Maximum Number of Device Variables", "hart_ip.pt.rsp.device_variables",
1579 FT_UINT8, BASE_DEC, NULL, 0x0,
1582 { &hf_hartip_pt_rsp_configuration_change_counter,
1583 { "Configuration Change Counter", "hart_ip.pt.rsp.configure_change",
1584 FT_UINT16, BASE_DEC, NULL, 0x0,
1587 { &hf_hartip_pt_rsp_extended_device_status,
1588 { "Extended Device Status", "hart_ip.pt.rsp.ext_device_status",
1589 FT_UINT8, BASE_HEX, NULL, 0x0,
1592 { &hf_hartip_pt_rsp_manufacturer_Identification_code,
1593 { "Manufacturer ID", "hart_ip.pt.rsp.manufacturer_Id",
1594 FT_UINT16, BASE_DEC, NULL, 0x0,
1597 { &hf_hartip_pt_rsp_private_label,
1598 { "Private Label", "hart_ip.pt.rsp.private_label",
1599 FT_UINT16, BASE_DEC, NULL, 0x0,
1602 { &hf_hartip_pt_rsp_device_profile,
1603 { "Device Profile", "hart_ip.pt.rsp.device_profile",
1604 FT_UINT8, BASE_DEC, NULL, 0x0,
1609 { &hf_hartip_pt_rsp_pv_percent_range,
1610 { "PV Percent Range", "hart_ip.pt.rsp.pv_percent_range",
1611 FT_FLOAT, BASE_NONE, NULL, 0x0,
1616 { &hf_hartip_pt_rsp_pv_loop_current,
1617 { "PV Loop Current", "hart_ip.pt.rsp.pv_loop_current",
1618 FT_FLOAT, BASE_NONE, NULL, 0x0,
1621 { &hf_hartip_pt_rsp_pv_units,
1622 { "PV Units", "hart_ip.pt.rsp.pv_units",
1623 FT_UINT8, BASE_DEC, NULL, 0x0,
1626 { &hf_hartip_pt_rsp_pv,
1627 { "PV", "hart_ip.pt.rsp.pv",
1628 FT_FLOAT, BASE_NONE, NULL, 0x0,
1631 { &hf_hartip_pt_rsp_sv_units,
1632 { "SV Units", "hart_ip.pt.rsp.sv_units",
1633 FT_UINT8, BASE_DEC, NULL, 0x0,
1636 { &hf_hartip_pt_rsp_sv,
1637 { "SV", "hart_ip.pt.rsp.sv",
1638 FT_FLOAT, BASE_NONE, NULL, 0x0,
1641 { &hf_hartip_pt_rsp_tv_units,
1642 { "TV Units", "hart_ip.pt.rsp.tv_units",
1643 FT_UINT8, BASE_DEC, NULL, 0x0,
1646 { &hf_hartip_pt_rsp_tv,
1647 { "TV", "hart_ip.pt.rsp.tv",
1648 FT_FLOAT, BASE_NONE, NULL, 0x0,
1651 { &hf_hartip_pt_rsp_qv_units,
1652 { "QV Units", "hart_ip.pt.rsp.qv_units",
1653 FT_UINT8, BASE_DEC, NULL, 0x0,
1656 { &hf_hartip_pt_rsp_qv,
1657 { "QV", "hart_ip.pt.rsp.qv",
1658 FT_FLOAT, BASE_NONE, NULL, 0x0,
1663 { &hf_hartip_pt_rsp_loop_current_mode,
1664 { "Loop Current Mode", "hart_ip.pt.rsp.loop_current_mode",
1665 FT_UINT8, BASE_HEX, NULL, 0x0,
1670 { &hf_hartip_pt_rsp_primary_var_classify,
1671 { "Primary Variable Classification", "hart_ip.pt.rsp.primary_variable_classification",
1672 FT_UINT8, BASE_HEX, NULL, 0x0,
1675 { &hf_hartip_pt_rsp_secondary_var_classify,
1676 { "Secondary Variable Classification", "hart_ip.pt.rsp.secondary_variable_classification",
1677 FT_UINT8, BASE_HEX, NULL, 0x0,
1680 { &hf_hartip_pt_rsp_tertiary_var_classify,
1681 { "Tertiary Variable Classification", "hart_ip.pt.rsp.tertiary_variable_classification",
1682 FT_UINT8, BASE_HEX, NULL, 0x0,
1685 { &hf_hartip_pt_rsp_quaternary_var_classify,
1686 { "Quaternary Variable Classification", "hart_ip.pt.rsp.quaternary_variable_classification",
1687 FT_UINT8, BASE_HEX, NULL, 0x0,
1692 { &hf_hartip_pt_rsp_slot0_device_var,
1693 { "Slot0 Device Variable", "hart_ip.pt.rsp.slot0_device_var",
1694 FT_UINT8, BASE_DEC, NULL, 0x0,
1697 { &hf_hartip_pt_rsp_slot0_device_var_classify,
1698 { "Slot0 Device Variable Classification", "hart_ip.pt.rsp.slot0_device_var_classification",
1699 FT_UINT8, BASE_DEC, NULL, 0x0,
1702 { &hf_hartip_pt_rsp_slot0_units,
1703 { "Slot0 Units", "hart_ip.pt.rsp.slot0_units",
1704 FT_UINT8, BASE_DEC, NULL, 0x0,
1707 { &hf_hartip_pt_rsp_slot0_device_var_value,
1708 { "Slot0 Device Variable Value", "hart_ip.pt.rsp.slot0_device_var_value",
1709 FT_FLOAT, BASE_NONE, NULL, 0x0,
1712 { &hf_hartip_pt_rsp_slot0_device_var_status,
1713 { "Slot0 Device Variable Status", "hart_ip.pt.rsp.slot0_device_var_status",
1714 FT_UINT8, BASE_HEX, NULL, 0x0,
1717 { &hf_hartip_pt_rsp_slot1_device_var,
1718 { "Slot1 Device Variable", "hart_ip.pt.rsp.slot1_device_var",
1719 FT_UINT8, BASE_DEC, NULL, 0x0,
1722 { &hf_hartip_pt_rsp_slot1_device_var_classify,
1723 { "Slot1 Device Variable Classification", "hart_ip.pt.rsp.slot1_device_var_classify",
1724 FT_UINT8, BASE_DEC, NULL, 0x0,
1727 { &hf_hartip_pt_rsp_slot1_units,
1728 { "Slot1 Units", "hart_ip.pt.rsp.slot1_units",
1729 FT_UINT8, BASE_DEC, NULL, 0x0,
1732 { &hf_hartip_pt_rsp_slot1_device_var_value,
1733 { "Slot1 Device Variable Value", "hart_ip.pt.rsp.slot1_device_var_value",
1734 FT_FLOAT, BASE_NONE, NULL, 0x0,
1737 { &hf_hartip_pt_rsp_slot1_device_var_status,
1738 { "Slot1 Device Variable Status", "hart_ip.pt.rsp.slot1_device_var_status",
1739 FT_UINT8, BASE_HEX, NULL, 0x0,
1742 { &hf_hartip_pt_rsp_slot2_device_var,
1743 { "Slot2 Device Variable", "hart_ip.pt.rsp.slot2_device_var",
1744 FT_UINT8, BASE_DEC, NULL, 0x0,
1747 { &hf_hartip_pt_rsp_slot2_device_var_classify,
1748 { "Slot2 Device Variable Classification", "hart_ip.pt.rsp.slot2_device_var_classify",
1749 FT_UINT8, BASE_DEC, NULL, 0x0,
1752 { &hf_hartip_pt_rsp_slot2_units,
1753 { "Slot2 Units", "hart_ip.pt.rsp.slot2_units",
1754 FT_UINT8, BASE_DEC, NULL, 0x0,
1757 { &hf_hartip_pt_rsp_slot2_device_var_value,
1758 { "Slot2 Device Variable Value", "hart_ip.pt.rsp.slot2_device_var_value",
1759 FT_FLOAT, BASE_NONE, NULL, 0x0,
1762 { &hf_hartip_pt_rsp_slot2_device_var_status,
1763 { "Slot2 Device Variable Status", "hart_ip.pt.rsp.slot2_device_var_status",
1764 FT_UINT8, BASE_HEX, NULL, 0x0,
1767 { &hf_hartip_pt_rsp_slot3_device_var,
1768 { "Slot3 Device Variable", "hart_ip.pt.rsp.slot3_device_var",
1769 FT_UINT8, BASE_DEC, NULL, 0x0,
1772 { &hf_hartip_pt_rsp_slot3_device_var_classify,
1773 { "Slot3 Device Variable Classification", "hart_ip.pt.rsp.slot3_device_var_classify",
1774 FT_UINT8, BASE_DEC, NULL, 0x0,
1777 { &hf_hartip_pt_rsp_slot3_units,
1778 { "Slot3 Units", "hart_ip.pt.rsp.slot3_units",
1779 FT_UINT8, BASE_DEC, NULL, 0x0,
1782 { &hf_hartip_pt_rsp_slot3_device_var_value,
1783 { "Slot3 Device Variable Value", "hart_ip.pt.rsp.slot3_device_var_value",
1784 FT_FLOAT, BASE_NONE, NULL, 0x0,
1787 { &hf_hartip_pt_rsp_slot3_device_var_status,
1788 { "Slot3 Device Variable Status", "hart_ip.pt.rsp.slot3_device_var_status",
1789 FT_UINT8, BASE_HEX, NULL, 0x0,
1792 { &hf_hartip_pt_rsp_slot4_device_var,
1793 { "Slot4 Device Variable", "hart_ip.pt.rsp.slot4_device_var",
1794 FT_UINT8, BASE_DEC, NULL, 0x0,
1797 { &hf_hartip_pt_rsp_slot4_device_var_classify,
1798 { "Slot4 Device Variable Classification", "hart_ip.pt.rsp.slot4_device_var_classify",
1799 FT_UINT8, BASE_DEC, NULL, 0x0,
1802 { &hf_hartip_pt_rsp_slot4_units,
1803 { "Slot4 Units", "hart_ip.pt.rsp.slot4_units",
1804 FT_UINT8, BASE_DEC, NULL, 0x0,
1807 { &hf_hartip_pt_rsp_slot4_device_var_value,
1808 { "Slot4 Device Variable Value", "hart_ip.pt.rsp.slot4_device_var_value",
1809 FT_FLOAT, BASE_NONE, NULL, 0x0,
1812 { &hf_hartip_pt_rsp_slot4_device_var_status,
1813 { "Slot4 Device Variable Status", "hart_ip.pt.rsp.slot4_device_var_status",
1814 FT_UINT8, BASE_HEX, NULL, 0x0,
1817 { &hf_hartip_pt_rsp_slot5_device_var,
1818 { "Slot5 Device Variable", "hart_ip.pt.rsp.slot5_device_var",
1819 FT_UINT8, BASE_DEC, NULL, 0x0,
1822 { &hf_hartip_pt_rsp_slot5_device_var_classify,
1823 { "Slot5 Device Variable Classification", "hart_ip.pt.rsp.slot5_device_var_classify",
1824 FT_UINT8, BASE_DEC, NULL, 0x0,
1827 { &hf_hartip_pt_rsp_slot5_units,
1828 { "Slot5 Units", "hart_ip.pt.rsp.slot5_units",
1829 FT_UINT8, BASE_DEC, NULL, 0x0,
1832 { &hf_hartip_pt_rsp_slot5_device_var_value,
1833 { "Slot5 Device Variable Value", "hart_ip.pt.rsp.slot5_device_var_value",
1834 FT_FLOAT, BASE_NONE, NULL, 0x0,
1837 { &hf_hartip_pt_rsp_slot5_device_var_status,
1838 { "Slot5 Device Variable Status", "hart_ip.pt.rsp.slot5_device_var_status",
1839 FT_UINT8, BASE_HEX, NULL, 0x0,
1842 { &hf_hartip_pt_rsp_slot6_device_var,
1843 { "Slot6 Device Variable", "hart_ip.pt.rsp.slot6_device_var",
1844 FT_UINT8, BASE_DEC, NULL, 0x0,
1847 { &hf_hartip_pt_rsp_slot6_device_var_classify,
1848 { "Slot6 Device Variable Classification", "hart_ip.pt.rsp.slot6_device_var_classify",
1849 FT_UINT8, BASE_DEC, NULL, 0x0,
1852 { &hf_hartip_pt_rsp_slot6_units,
1853 { "Slot6 Units", "hart_ip.pt.rsp.slot6_units",
1854 FT_UINT8, BASE_DEC, NULL, 0x0,
1857 { &hf_hartip_pt_rsp_slot6_device_var_value,
1858 { "Slot6 Device Variable Value", "hart_ip.pt.rsp.slot6_device_var_value",
1859 FT_FLOAT, BASE_NONE, NULL, 0x0,
1862 { &hf_hartip_pt_rsp_slot6_device_var_status,
1863 { "Slot6 Device Variable Status", "hart_ip.pt.rsp.slot6_device_var_status",
1864 FT_UINT8, BASE_HEX, NULL, 0x0,
1867 { &hf_hartip_pt_rsp_slot7_device_var,
1868 { "Slot7 Device Variable", "hart_ip.pt.rsp.slot7_device_var",
1869 FT_UINT8, BASE_DEC, NULL, 0x0,
1872 { &hf_hartip_pt_rsp_slot7_device_var_classify,
1873 { "Slot7 Device Variable Classification", "hart_ip.pt.rsp.slot7_device_var_classify",
1874 FT_UINT8, BASE_DEC, NULL, 0x0,
1877 { &hf_hartip_pt_rsp_slot7_units,
1878 { "Slot7 Units", "hart_ip.pt.rsp.slot7_units",
1879 FT_UINT8, BASE_DEC, NULL, 0x0,
1882 { &hf_hartip_pt_rsp_slot7_device_var_value,
1883 { "Slot7 Device Variable Value", "hart_ip.pt.rsp.slot7_device_var_value",
1884 FT_FLOAT, BASE_NONE, NULL, 0x0,
1887 { &hf_hartip_pt_rsp_slot7_device_var_status,
1888 { "Slot7 Device Variable Status", "hart_ip.pt.rsp.slot7_device_var_status",
1889 FT_UINT8, BASE_HEX, NULL, 0x0,
1892 { &hf_hartip_pt_rsp_slot0_timestamp,
1893 { "Slot0 Data TimeStamp", "hart_ip.pt.rsp.slot0_data_timestamp",
1894 FT_BYTES, BASE_NONE, NULL, 0x0,
1899 { &hf_hartip_pt_rsp_packed_descriptor,
1900 { "Descriptor", "hart_ip.pt.rsp.descriptor",
1901 FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
1904 { &hf_hartip_pt_rsp_day,
1905 { "Day", "hart_ip.pt.rsp.day",
1906 FT_UINT8, BASE_DEC, NULL, 0x0,
1909 { &hf_hartip_pt_rsp_month,
1910 { "Month", "hart_ip.pt.rsp.month",
1911 FT_UINT8, BASE_DEC, NULL, 0x0,
1914 { &hf_hartip_pt_rsp_year,
1915 { "Year", "hart_ip.pt.rsp.year",
1916 FT_UINT8, BASE_DEC, NULL, 0x0,
1921 { &hf_hartip_pt_rsp_transducer_serial_number,
1922 { "Transducer Serail Number", "hart_ip.pt.rsp.transducer_serail_number",
1923 FT_BYTES, BASE_NONE, NULL, 0x0,
1926 { &hf_hartip_pt_rsp_transducer_limit_min_span_units,
1927 { "Transducer Limit Min Span Units", "hart_ip.pt.rsp.transducer_limit_min_span_units",
1928 FT_UINT8, BASE_HEX, NULL, 0x0,
1931 { &hf_hartip_pt_rsp_upper_transducer_limit,
1932 { "Upper Transducer Limit", "hart_ip.pt.rsp.upper_transducer_limit",
1933 FT_FLOAT, BASE_NONE, NULL, 0x0,
1936 { &hf_hartip_pt_rsp_lower_transducer_limit,
1937 { "Lower Transducer Limit", "hart_ip.pt.rsp.lower_transducer_limit",
1938 FT_FLOAT, BASE_NONE, NULL, 0x0,
1941 { &hf_hartip_pt_rsp_minimum_span,
1942 { "Minimum Span", "hart_ip.pt.rsp.minimum_span",
1943 FT_FLOAT, BASE_NONE, NULL, 0x0,
1948 { &hf_hartip_pt_rsp_pv_alarm_selection_code,
1949 { "PV Alarm Selection Code", "hart_ip.pt.rsp.pv_alarm_selection_code",
1950 FT_UINT8, BASE_HEX, NULL, 0x0,
1953 { &hf_hartip_pt_rsp_pv_transfer_function_code,
1954 { "PV Transfer Function Code", "hart_ip.pt.rsp.pv_transfer_function_code",
1955 FT_UINT8, BASE_HEX, NULL, 0x0,
1958 { &hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units,
1959 { "PV Upper and Lower Range Values Units", "hart_ip.pt.rsp.pv_upper_and_lower_range_values_units",
1960 FT_UINT8, BASE_HEX, NULL, 0x0,
1963 { &hf_hartip_pt_rsp_pv_upper_range_value,
1964 { "PV Upper Range Value", "hart_ip.pt.rsp.pv_upper_range_value",
1965 FT_FLOAT, BASE_NONE, NULL, 0x0,
1968 { &hf_hartip_pt_rsp_pv_lower_range_value,
1969 { "PV Lower Range Value", "hart_ip.pt.rsp.pv_lower_range_value",
1970 FT_FLOAT, BASE_NONE, NULL, 0x0,
1973 { &hf_hartip_pt_rsp_pv_damping_value,
1974 { "PV Damping Value", "hart_ip.pt.rsp.pv_damping_value",
1975 FT_FLOAT, BASE_NONE, NULL, 0x0,
1978 { &hf_hartip_pt_rsp_write_protect_code,
1979 { "Write Protect Code", "hart_ip.pt.rsp.write_protect_code",
1980 FT_UINT8, BASE_HEX, NULL, 0x0,
1983 { &hf_hartip_pt_rsp_reserved,
1984 { "Reserved", "hart_ip.pt.rsp.reserved",
1985 FT_UINT8, BASE_HEX, NULL, 0x0,
1988 { &hf_hartip_pt_rsp_pv_analog_channel_flags,
1989 { "PV Analog Channel Flags", "hart_ip.pt.rsp.pv_analog_channel_flags",
1990 FT_UINT8, BASE_HEX, NULL, 0x0,
1994 /* command 16 and 19 */
1995 { &hf_hartip_pt_rsp_final_assembly_number,
1996 { "Final Assembly Number", "hart_ip.pt.rsp.final_assembly_numbe",
1997 FT_BYTES, BASE_NONE, NULL, 0x0,
2002 { &hf_hartip_pt_rsp_tag,
2003 { "Tag", "hart_ip.pt.rsp.tag",
2004 FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2009 { &hf_hartip_pt_rsp_message,
2010 { "Message", "hart_ip.pt.rsp.message",
2011 FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2016 { &hf_hartip_pt_rsp_device_sp_status,
2017 { "Device-Specific Status", "hart_ip.pt.rsp.device_sp_status",
2018 FT_BYTES, BASE_NONE, NULL, 0x0,
2021 { &hf_hartip_pt_rsp_device_op_mode,
2022 { "Device Operating Mode", "hart_ip.pt.rsp.device_op_mode",
2023 FT_UINT8, BASE_DEC, NULL, 0x0,
2026 { &hf_hartip_pt_rsp_standardized_status_0,
2027 { "Standardized Status 0", "hart_ip.pt.rsp.standardized_status_0",
2028 FT_UINT8, BASE_HEX, NULL, 0x0,
2031 { &hf_hartip_pt_rsp_standardized_status_1,
2032 { "Standardized Status 1", "hart_ip.pt.rsp.standardized_status_1",
2033 FT_UINT8, BASE_HEX, NULL, 0x0,
2036 { &hf_hartip_pt_rsp_analog_channel_saturated,
2037 { "Analog Channel Saturated", "hart_ip.pt.rsp.analog_channel_saturated",
2038 FT_UINT8, BASE_DEC, NULL, 0x0,
2041 { &hf_hartip_pt_rsp_standardized_status_2,
2042 { "Standardized Status 2", "hart_ip.pt.rsp.standardized_status_2",
2043 FT_UINT8, BASE_HEX, NULL, 0x0,
2046 { &hf_hartip_pt_rsp_standardized_status_3,
2047 { "Standardized Status 3", "hart_ip.pt.rsp.standardized_status_3",
2048 FT_UINT8, BASE_HEX, NULL, 0x0,
2051 { &hf_hartip_pt_rsp_analog_channel_fixed,
2052 { "Analog Channel Fixed", "hart_ip.pt.rsp.analog_channel_fixed",
2053 FT_UINT8, BASE_DEC, NULL, 0x0,
2058 { &hf_hartip_pt_rsp_io_card,
2059 { "IO Card", "hart_ip.pt.rsp.io_card",
2060 FT_UINT8, BASE_DEC, NULL, 0x0,
2063 { &hf_hartip_pt_rsp_channel,
2064 { "Channel", "hart_ip.pt.rsp.channel",
2065 FT_UINT8, BASE_DEC, NULL, 0x0,
2068 { &hf_hartip_pt_rsp_embedded_cmd_delimiter,
2069 { "Embedded Command Delimter", "hart_ip.pt.rsp.embedded_command_delimter",
2070 FT_UINT8, BASE_HEX, NULL, 0x0,
2073 { &hf_hartip_pt_rsp_poll_address,
2074 { "Poll Address", "hart_ip.pt.rsp.poll_address",
2075 FT_UINT8, BASE_DEC, NULL, 0x0,
2078 { &hf_hartip_pt_rsp_embedded_cmd,
2079 { "Embedded Command", "hart_ip.pt.rsp.embedded_command",
2080 FT_UINT8, BASE_DEC, NULL, 0x0,
2085 { &hf_hartip_pt_rsp_number_of_commands,
2086 { "Number of Commands", "hart_ip.pt.rsp.number_of_commands",
2087 FT_UINT8, BASE_DEC, NULL, 0x0,
2090 /* command 31 and 178 */
2091 { &hf_hartip_pt_rsp_command_number,
2092 { "Command number", "hart_ip.pt.rsp.command_number",
2093 FT_UINT16, BASE_DEC, NULL, 0x0,
2096 { &hf_hartip_pt_rsp_data,
2097 { "Data", "hart_ip.pt.rsp.data",
2098 FT_BYTES, BASE_NONE, NULL, 0x0,
2101 /* command 77 and 178 */
2102 { &hf_hartip_pt_rsp_command_byte_count,
2103 { "Command byte count", "hart_ip.pt.rsp.command_byte_count",
2104 FT_UINT8, BASE_DEC, NULL, 0x0,
2109 { &hf_hartip_pt_rsp_index_of_first_discrete_var,
2110 { "Index of First Discrete Variable", "hart_ip.pt.rsp.index_of_first_discrete_var",
2111 FT_UINT16, BASE_DEC, NULL, 0x0,
2114 { &hf_hartip_pt_rsp_number_of_discrete_vars,
2115 { "Number of Discrete Variables", "hart_ip.pt.rsp.number_of_discrete_vars",
2116 FT_UINT8, BASE_HEX, NULL, 0x0,
2119 { &hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
2120 { "TimeStamp for Most Recent Discrete Change", "hart_ip.pt.rsp.timestamp_for_most_recent_discrete_change",
2121 FT_BYTES, BASE_NONE, NULL, 0x0,
2124 { &hf_hartip_pt_rsp_slot0_discrete_var_state,
2125 { "Slot0 Discrete Variable State", "hart_ip.pt.rsp.slot0_discrete_var_state",
2126 FT_UINT16, BASE_DEC, NULL, 0x0,
2129 { &hf_hartip_pt_rsp_slot0_discrete_var_status,
2130 { "Slot0 Discrete Variable Status", "hart_ip.pt.rsp.slot0_discrete_var_status",
2131 FT_UINT8, BASE_HEX, NULL, 0x0,
2134 { &hf_hartip_pt_rsp_slot1_discrete_var_state,
2135 { "Slot1 Discrete Variable State", "hart_ip.pt.rsp.slot1_discrete_var_state",
2136 FT_UINT16, BASE_DEC, NULL, 0x0,
2139 { &hf_hartip_pt_rsp_slot1_discrete_var_status,
2140 { "Slot1 Discrete Variable Status", "hart_ip.pt.rsp.slot1_discrete_var_status",
2141 FT_UINT8, BASE_HEX, NULL, 0x0,
2144 { &hf_hartip_pt_rsp_slot2_discrete_var_state,
2145 { "Slot2 Discrete Variable State", "hart_ip.pt.rsp.slot2_discrete_var_state",
2146 FT_UINT16, BASE_DEC, NULL, 0x0,
2149 { &hf_hartip_pt_rsp_slot2_discrete_var_status,
2150 { "Slot2 Discrete Variable Status", "hart_ip.pt.rsp.slot2_discrete_var_status",
2151 FT_UINT8, BASE_HEX, NULL, 0x0,
2154 { &hf_hartip_pt_rsp_slot3_discrete_var_state,
2155 { "Slot3 Discrete Variable State", "hart_ip.pt.rsp.slot3_discrete_var_state",
2156 FT_UINT16, BASE_DEC, NULL, 0x0,
2159 { &hf_hartip_pt_rsp_slot3_discrete_var_status,
2160 { "Slot3 Discrete Variable Status", "hart_ip.pt.rsp.slot3_discrete_var_status",
2161 FT_UINT8, BASE_HEX, NULL, 0x0,
2164 { &hf_hartip_pt_rsp_slot4_discrete_var_state,
2165 { "Slot4 Discrete Variable State", "hart_ip.pt.rsp.slot4_discrete_var_state",
2166 FT_UINT16, BASE_DEC, NULL, 0x0,
2169 { &hf_hartip_pt_rsp_slot4_discrete_var_status,
2170 { "Slot4 Discrete Variable Status", "hart_ip.pt.rsp.slot4_discrete_var_status",
2171 FT_UINT8, BASE_HEX, NULL, 0x0,
2174 { &hf_hartip_pt_rsp_slot5_discrete_var_state,
2175 { "Slot5 Discrete Variable State", "hart_ip.pt.rsp.slot5_discrete_var_state",
2176 FT_UINT16, BASE_DEC, NULL, 0x0,
2179 { &hf_hartip_pt_rsp_slot5_discrete_var_status,
2180 { "Slot5 Discrete Variable Status", "hart_ip.pt.rsp.slot5_discrete_var_status",
2181 FT_UINT8, BASE_HEX, NULL, 0x0,
2186 static gint *ett[] = {
2192 static ei_register_info ei[] = {
2193 { &ei_hartip_data_none, { "hart_ip.data.none", PI_PROTOCOL, PI_NOTE, "No data", EXPFILL }},
2194 { &ei_hartip_data_unexpected, { "hart_ip.data.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected message body", EXPFILL }},
2197 module_t *hartip_module;
2198 expert_module_t* expert_hartip;
2200 proto_hartip = proto_register_protocol("HART_IP Protocol", "HART_IP", "hart_ip");
2201 proto_register_field_array(proto_hartip, hf, array_length(hf));
2202 proto_register_subtree_array(ett, array_length(ett));
2203 expert_hartip = expert_register_protocol(proto_hartip);
2204 expert_register_field_array(expert_hartip, ei, array_length(ei));
2206 hartip_module = prefs_register_protocol(proto_hartip, NULL);
2207 prefs_register_bool_preference(hartip_module, "desegment",
2208 "Desegment all HART-IP messages spanning multiple TCP segments",
2209 "Whether the HART-IP dissector should desegment all messages spanning multiple TCP segments",
2212 hartip_tap = register_tap("hart_ip");
2216 proto_reg_handoff_hartip(void)
2218 hartip_tcp_handle = create_dissector_handle(dissect_hartip_tcp, proto_hartip);
2219 hartip_udp_handle = create_dissector_handle(dissect_hartip_udp, proto_hartip);
2220 dissector_add_uint_with_preference("udp.port", HARTIP_PORT, hartip_udp_handle);
2221 dissector_add_uint_with_preference("tcp.port", HARTIP_PORT, hartip_tcp_handle);
2223 stats_tree_register("hart_ip", "hart_ip", "HART-IP", 0,
2224 hartip_stats_tree_packet, hartip_stats_tree_init, NULL);
2228 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2233 * indent-tabs-mode: nil
2236 * vi: set shiftwidth=2 tabstop=8 expandtab:
2237 * :indentSize=2:tabSize=8:noTabs=true: