2 * Routines for HART-IP packet dissection
3 * Copyright 2012, Bill Schiller <bill.schiller@emerson.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-mbtcp.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/conversation.h>
31 #include <epan/packet.h>
33 #include <epan/stats_tree.h>
34 #include <epan/expert.h>
35 #include <epan/prefs.h>
36 #include <epan/wmem/wmem.h>
37 #include "packet-tcp.h"
39 static dissector_handle_t hartip_tcp_handle
;
40 static dissector_handle_t hartip_udp_handle
;
42 static gboolean hartip_desegment
= TRUE
;
44 static int proto_hartip
= -1;
45 static int hf_hartip_hdr_version
= -1;
46 static int hf_hartip_hdr_message_id
= -1;
47 static int hf_hartip_hdr_message_type
= -1;
48 static int hf_hartip_hdr_status
= -1;
49 static int hf_hartip_hdr_transaction_id
= -1;
50 static int hf_hartip_hdr_msg_length
= -1;
52 static int hf_hartip_data
= -1;
53 static int hf_hartip_master_type
= -1;
54 static int hf_hartip_inactivity_close_timer
= -1;
55 static int hf_hartip_error_code
= -1;
57 static int hf_hartip_pt_preambles
= -1;
58 static int hf_hartip_pt_delimiter
= -1;
59 static int hf_hartip_pt_short_addr
= -1;
60 static int hf_hartip_pt_long_addr
= -1;
61 static int hf_hartip_pt_command
= -1;
62 static int hf_hartip_pt_length
= -1;
63 static int hf_hartip_pt_response_code
= -1;
64 static int hf_hartip_pt_device_status
= -1;
65 static int hf_hartip_pt_payload
= -1;
66 static int hf_hartip_pt_checksum
= -1;
68 static gint ett_hartip
= -1;
69 static gint ett_hartip_hdr
= -1;
70 static gint ett_hartip_body
= -1;
72 static expert_field ei_hartip_data_none
= EI_INIT
;
73 static expert_field ei_hartip_data_unexpected
= EI_INIT
;
75 /* Command 0 response */
76 static int hf_hartip_pt_rsp_expansion_code
= -1;
77 static int hf_hartip_pt_rsp_expanded_device_type
= -1;
78 static int hf_hartip_pt_rsp_req_min_preambles
= -1;
79 static int hf_hartip_pt_rsp_hart_protocol_major_rev
= -1;
80 static int hf_hartip_pt_rsp_device_rev
= -1;
81 static int hf_hartip_pt_rsp_software_rev
= -1;
82 static int hf_hartip_pt_rsp_hardware_rev_physical_signal
= -1;
83 static int hf_hartip_pt_rsp_flage
= -1;
84 static int hf_hartip_pt_rsp_device_id
= -1;
85 static int hf_hartip_pt_rsp_rsp_min_preambles
= -1;
86 static int hf_hartip_pt_rsp_max_device_variables
= -1;
87 static int hf_hartip_pt_rsp_configuration_change_counter
= -1;
88 static int hf_hartip_pt_rsp_extended_device_status
= -1;
89 static int hf_hartip_pt_rsp_manufacturer_Identification_code
= -1;
90 static int hf_hartip_pt_rsp_private_label
= -1;
91 static int hf_hartip_pt_rsp_device_profile
= -1;
93 /* Command 2 response */
94 static int hf_hartip_pt_rsp_pv_percent_range
= -1;
96 /* Command 3 response */
97 static int hf_hartip_pt_rsp_pv_loop_current
= -1;
98 static int hf_hartip_pt_rsp_pv_units
= -1;
99 static int hf_hartip_pt_rsp_pv
= -1;
100 static int hf_hartip_pt_rsp_sv_units
= -1;
101 static int hf_hartip_pt_rsp_sv
= -1;
102 static int hf_hartip_pt_rsp_tv_units
= -1;
103 static int hf_hartip_pt_rsp_tv
= -1;
104 static int hf_hartip_pt_rsp_qv_units
= -1;
105 static int hf_hartip_pt_rsp_qv
= -1;
107 /* Command 9 response */
108 static int hf_hartip_pt_rsp_slot0_device_var
= -1;
109 static int hf_hartip_pt_rsp_slot0_device_var_classify
= -1;
110 static int hf_hartip_pt_rsp_slot0_units
= -1;
111 static int hf_hartip_pt_rsp_slot0_device_var_value
= -1;
112 static int hf_hartip_pt_rsp_slot0_device_var_status
= -1;
114 static int hf_hartip_pt_rsp_slot1_device_var
= -1;
115 static int hf_hartip_pt_rsp_slot1_device_var_classify
= -1;
116 static int hf_hartip_pt_rsp_slot1_units
= -1;
117 static int hf_hartip_pt_rsp_slot1_device_var_value
= -1;
118 static int hf_hartip_pt_rsp_slot1_device_var_status
= -1;
120 static int hf_hartip_pt_rsp_slot2_device_var
= -1;
121 static int hf_hartip_pt_rsp_slot2_device_var_classify
= -1;
122 static int hf_hartip_pt_rsp_slot2_units
= -1;
123 static int hf_hartip_pt_rsp_slot2_device_var_value
= -1;
124 static int hf_hartip_pt_rsp_slot2_device_var_status
= -1;
126 static int hf_hartip_pt_rsp_slot3_device_var
= -1;
127 static int hf_hartip_pt_rsp_slot3_device_var_classify
= -1;
128 static int hf_hartip_pt_rsp_slot3_units
= -1;
129 static int hf_hartip_pt_rsp_slot3_device_var_value
= -1;
130 static int hf_hartip_pt_rsp_slot3_device_var_status
= -1;
132 static int hf_hartip_pt_rsp_slot4_device_var
= -1;
133 static int hf_hartip_pt_rsp_slot4_device_var_classify
= -1;
134 static int hf_hartip_pt_rsp_slot4_units
= -1;
135 static int hf_hartip_pt_rsp_slot4_device_var_value
= -1;
136 static int hf_hartip_pt_rsp_slot4_device_var_status
= -1;
138 static int hf_hartip_pt_rsp_slot5_device_var
= -1;
139 static int hf_hartip_pt_rsp_slot5_device_var_classify
= -1;
140 static int hf_hartip_pt_rsp_slot5_units
= -1;
141 static int hf_hartip_pt_rsp_slot5_device_var_value
= -1;
142 static int hf_hartip_pt_rsp_slot5_device_var_status
= -1;
144 static int hf_hartip_pt_rsp_slot6_device_var
= -1;
145 static int hf_hartip_pt_rsp_slot6_device_var_classify
= -1;
146 static int hf_hartip_pt_rsp_slot6_units
= -1;
147 static int hf_hartip_pt_rsp_slot6_device_var_value
= -1;
148 static int hf_hartip_pt_rsp_slot6_device_var_status
= -1;
150 static int hf_hartip_pt_rsp_slot7_device_var
= -1;
151 static int hf_hartip_pt_rsp_slot7_device_var_classify
= -1;
152 static int hf_hartip_pt_rsp_slot7_units
= -1;
153 static int hf_hartip_pt_rsp_slot7_device_var_value
= -1;
154 static int hf_hartip_pt_rsp_slot7_device_var_status
= -1;
156 static int hf_hartip_pt_rsp_slot0_timestamp
= -1;
158 /* Command 13 response */
159 static int hf_hartip_pt_rsp_packed_descriptor
= -1;
160 static int hf_hartip_pt_rsp_day
= -1;
161 static int hf_hartip_pt_rsp_month
= -1;
162 static int hf_hartip_pt_rsp_year
= -1;
165 static int hf_hartip_pt_rsp_tag
= -1;
167 /* response Message */
168 static int hf_hartip_pt_rsp_message
= -1;
170 /* Command 48 response */
171 static int hf_hartip_pt_rsp_device_sp_status
= -1;
172 static int hf_hartip_pt_rsp_device_op_mode
= -1;
173 static int hf_hartip_pt_rsp_standardized_status_0
= -1;
174 static int hf_hartip_pt_rsp_standardized_status_1
= -1;
175 static int hf_hartip_pt_rsp_analog_channel_saturated
= -1;
176 static int hf_hartip_pt_rsp_standardized_status_2
= -1;
177 static int hf_hartip_pt_rsp_standardized_status_3
= -1;
178 static int hf_hartip_pt_rsp_analog_channel_fixed
= -1;
180 #define HARTIP_HEADER_LENGTH 8
181 #define HARTIP_PORT 5094
184 typedef struct _hartip_hdr
{
189 guint16 transaction_id
;
194 #define SESSION_INITIATE_ID 0
195 #define SESSION_CLOSE_ID 1
196 #define KEEP_ALIVE_ID 2
197 #define PASS_THROUGH_ID 3
200 #define REQUEST_MSG_TYPE 0
201 #define RESPONSE_MSG_TYPE 1
202 #define ERROR_MSG_TYPE 2
204 static const value_string hartip_message_id_values
[] = {
205 { SESSION_INITIATE_ID
, "Session Initiate" },
206 { SESSION_CLOSE_ID
, "Session Close" },
207 { KEEP_ALIVE_ID
, "Keep Alive" },
208 { PASS_THROUGH_ID
, "Pass Through" },
212 static const value_string hartip_message_type_values
[] = {
213 { REQUEST_MSG_TYPE
, "Request" },
214 { RESPONSE_MSG_TYPE
, "Response" },
215 { ERROR_MSG_TYPE
, "Error" },
220 #define SECONDARY_MASTER_TYPE 0
221 #define PRIMARY_MASTER_TYPE 1
223 static const value_string hartip_master_type_values
[] = {
224 { SECONDARY_MASTER_TYPE
, "Secondary Host" },
225 { PRIMARY_MASTER_TYPE
, "Primary Host" },
230 #define SESSION_CLOSED_ERROR 0
231 #define PRIMARY_SESSION_UNAVAILABLE_ERROR 1
232 #define SERVICE_UNAVAILABLE_ERROR 2
234 static const value_string hartip_error_code_values
[] = {
235 { SESSION_CLOSED_ERROR
, "Session closed" },
236 { PRIMARY_SESSION_UNAVAILABLE_ERROR
, "Primary session unavailable" },
237 { SERVICE_UNAVAILABLE_ERROR
, "Service unavailable" },
241 /* Handle for statistics tap. */
242 static int hartip_tap
= -1;
244 /* Structure used for passing data for statistics processing. */
245 typedef struct _hartip_tap_info
{
250 /* Names of items in statistics tree. */
251 static const gchar
* st_str_packets
= "Total HART_IP Packets";
252 static const gchar
* st_str_requests
= "Request Packets";
253 static const gchar
* st_str_responses
= "Response Packets";
254 static const gchar
* st_str_errors
= "Error Packets";
256 /* Handles of items in statistics tree. */
257 static int st_node_packets
= -1;
258 static int st_node_requests
= -1;
259 static int st_node_responses
= -1;
260 static int st_node_errors
= -1;
263 hartip_stats_tree_init(stats_tree
* st
)
265 st_node_packets
= stats_tree_create_node(st
, st_str_packets
, 0, TRUE
);
266 st_node_requests
= stats_tree_create_pivot(st
, st_str_requests
, st_node_packets
);
267 st_node_responses
= stats_tree_create_node(st
, st_str_responses
, st_node_packets
, TRUE
);
268 st_node_errors
= stats_tree_create_node(st
, st_str_errors
, st_node_packets
, TRUE
);
272 hartip_stats_tree_packet(stats_tree
* st
, packet_info
* pinfo _U_
,
273 epan_dissect_t
* edt _U_
, const void* p
)
275 const hartip_tap_info
*tapinfo
= (const hartip_tap_info
*)p
;
276 const gchar
*message_type_node_str
, *message_id_node_str
;
277 int message_type_node
;
279 switch (tapinfo
->message_type
) {
280 case REQUEST_MSG_TYPE
:
281 message_type_node_str
= st_str_requests
;
282 message_type_node
= st_node_requests
;
284 case RESPONSE_MSG_TYPE
:
285 message_type_node_str
= st_str_responses
;
286 message_type_node
= st_node_responses
;
289 message_type_node_str
= st_str_errors
;
290 message_type_node
= st_node_errors
;
293 return 0; /* Don't want to track invalid messages for now. */
296 message_id_node_str
= val_to_str(tapinfo
->message_id
,
297 hartip_message_id_values
,
298 "Unknown message %d");
300 tick_stat_node(st
, (guint8
*)st_str_packets
, 0, FALSE
);
301 tick_stat_node(st
, (guint8
*)message_type_node_str
, st_node_packets
, FALSE
);
302 tick_stat_node(st
, (guint8
*)message_id_node_str
, message_type_node
, FALSE
);
308 dissect_empty_body(proto_tree
*tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
309 gint offset
, gint bodylen
)
313 ti
= proto_tree_add_item(tree
, hf_hartip_data
, tvb
, offset
, bodylen
, ENC_NA
);
315 expert_add_info(pinfo
, ti
, &ei_hartip_data_none
);
317 expert_add_info(pinfo
, ti
, &ei_hartip_data_unexpected
);
323 dissect_session_init(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
,
327 proto_tree_add_item(body_tree
, hf_hartip_master_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
330 proto_tree_add_item(body_tree
, hf_hartip_inactivity_close_timer
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
332 proto_tree_add_item(body_tree
, hf_hartip_data
, tvb
, offset
, bodylen
, ENC_NA
);
339 dissect_error(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
342 proto_tree_add_item(body_tree
, hf_hartip_error_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
344 proto_tree_add_item(body_tree
, hf_hartip_data
, tvb
, offset
, bodylen
, ENC_NA
);
351 dissect_session_close(proto_tree
*body_tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
352 gint offset
, gint bodylen
)
354 return dissect_empty_body(body_tree
, pinfo
, tvb
, offset
, bodylen
);
358 dissect_keep_alive(proto_tree
*body_tree
, packet_info
* pinfo
, tvbuff_t
*tvb
,
359 gint offset
, gint bodylen
)
361 return dissect_empty_body(body_tree
, pinfo
, tvb
, offset
, bodylen
);
365 dissect_byte(proto_tree
*tree
, int hf
, tvbuff_t
*tvb
, gint offset
)
367 proto_tree_add_item(tree
, hf
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
372 dissect_short(proto_tree
*tree
, int hf
, tvbuff_t
*tvb
, gint offset
)
374 proto_tree_add_item(tree
, hf
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
379 dissect_float(proto_tree
*tree
, int hf
, tvbuff_t
*tvb
, gint offset
)
381 proto_tree_add_item(tree
, hf
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
386 dissect_string(proto_tree
*tree
, int hf
, const char *name
, int len
,
387 tvbuff_t
*tvb
, gint offset
)
392 str
= (char *)wmem_alloc(wmem_packet_scope(), 256);
394 ti
= proto_tree_add_item(tree
, hf
, tvb
, offset
, len
, ENC_NA
);
396 (void) tvb_get_nstringz0(tvb
, offset
, len
+ 1, str
);
397 proto_item_set_text(ti
, "%s: %s", name
, str
);
404 dissect_packAscii(proto_tree
*tree
, int hf
, const char *name
, int len
,
405 tvbuff_t
*tvb
, gint offset
)
409 gushort usMaxGroups
; /* Number of 4 byte groups to pack. */
418 str
= (char *)wmem_alloc(wmem_packet_scope(), 256+1);
420 ti
= proto_tree_add_item(tree
, hf
, tvb
, offset
, len
, ENC_NA
);
422 DISSECTOR_ASSERT(len
< 3 * (256/4));
423 tmp
= (guint8
*)wmem_alloc0(wmem_packet_scope(), len
);
424 tvb_memcpy(tvb
, tmp
, offset
, len
);
427 usMaxGroups
= (gushort
)(len
/ 3);
428 for (usGroupCnt
= 0; usGroupCnt
< usMaxGroups
; usGroupCnt
++) {
430 * First unpack 3 bytes into a group of 4 bytes, clearing bits 6 & 7.
432 buf
[0] = (gushort
)(tmp
[iIndex
] >> 2);
433 buf
[1] = (gushort
)(((tmp
[iIndex
] << 4) & 0x30) | (tmp
[iIndex
+ 1] >> 4));
434 buf
[2] = (gushort
)(((tmp
[iIndex
+ 1] << 2) & 0x3C) | (tmp
[iIndex
+ 2] >> 6));
435 buf
[3] = (gushort
)(tmp
[iIndex
+ 2] & 0x3F);
439 * Now transfer to unpacked area, setting bit 6 to complement of bit 5.
441 for (usIdx
= 0; usIdx
< 4; usIdx
++) {
442 usMask
= (gushort
)(((buf
[usIdx
] & 0x20) << 1) ^ 0x40);
443 DISSECTOR_ASSERT(i
< 256);
444 str
[i
++] = (gchar
)(buf
[usIdx
] | usMask
);
448 proto_item_set_text(ti
, "%s: %s", name
, str
);
454 dissect_timestamp(proto_tree
*tree
, int hf
, const char *name
, int len
,
455 tvbuff_t
*tvb
, gint offset
)
464 ti
= proto_tree_add_item(tree
, hf
, tvb
, offset
, len
, ENC_NA
);
465 t
= tvb_get_ntohl(tvb
, offset
);
474 hrs
= (guint
)(t
/ 60);
477 proto_item_set_text(ti
, "%s: %02d:%02d:%02d.%03d", name
, hrs
, mins
, secs
, ms
);
482 dissect_cmd0(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
485 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_expansion_code
, tvb
, offset
);
486 offset
+= dissect_short(body_tree
, hf_hartip_pt_rsp_expanded_device_type
, tvb
, offset
);
487 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_req_min_preambles
, tvb
, offset
);
488 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_hart_protocol_major_rev
, tvb
, offset
);
489 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_device_rev
, tvb
, offset
);
490 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_software_rev
, tvb
, offset
);
491 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_hardware_rev_physical_signal
, tvb
, offset
);
492 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_flage
, tvb
, offset
);
493 proto_tree_add_item(body_tree
, hf_hartip_pt_rsp_device_id
, tvb
, offset
, 3, ENC_NA
);
495 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_rsp_min_preambles
, tvb
, offset
);
496 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_max_device_variables
, tvb
, offset
);
497 offset
+= dissect_short(body_tree
, hf_hartip_pt_rsp_configuration_change_counter
, tvb
, offset
);
498 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_extended_device_status
, tvb
, offset
);
499 offset
+= dissect_short(body_tree
, hf_hartip_pt_rsp_manufacturer_Identification_code
, tvb
, offset
);
500 offset
+= dissect_short(body_tree
, hf_hartip_pt_rsp_private_label
, tvb
, offset
);
501 /*offset += */dissect_byte(body_tree
, hf_hartip_pt_rsp_device_profile
, tvb
, offset
);
510 dissect_cmd1(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
513 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_pv_units
, tvb
, offset
);
514 /*offset += */dissect_float(body_tree
, hf_hartip_pt_rsp_pv
, tvb
, offset
);
522 dissect_cmd2(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
525 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_pv_loop_current
, tvb
, offset
);
526 /*offset += */dissect_float(body_tree
, hf_hartip_pt_rsp_pv_percent_range
, tvb
, offset
);
534 dissect_cmd3(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
537 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_pv_loop_current
, tvb
, offset
);
538 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_pv_units
, tvb
, offset
);
539 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_pv
, tvb
, offset
);
540 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_sv_units
, tvb
, offset
);
541 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_sv
, tvb
, offset
);
542 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_tv_units
, tvb
, offset
);
543 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_tv
, tvb
, offset
);
544 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_qv_units
, tvb
, offset
);
545 /*offset += */dissect_float(body_tree
, hf_hartip_pt_rsp_qv
, tvb
, offset
);
554 dissect_cmd9(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
557 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_extended_device_status
, tvb
, offset
);
558 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot0_device_var
, tvb
, offset
);
559 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot0_device_var_classify
, tvb
, offset
);
560 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot0_units
, tvb
, offset
);
561 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot0_device_var_value
, tvb
, offset
);
562 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot0_device_var_status
, tvb
, offset
);
565 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot1_device_var
, tvb
, offset
);
566 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot1_device_var_classify
, tvb
, offset
);
567 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot1_units
, tvb
, offset
);
568 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot1_device_var_value
, tvb
, offset
);
569 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot1_device_var_status
, tvb
, offset
);
573 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot2_device_var
, tvb
, offset
);
574 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot2_device_var_classify
, tvb
, offset
);
575 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot2_units
, tvb
, offset
);
576 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot2_device_var_value
, tvb
, offset
);
577 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot2_device_var_status
, tvb
, offset
);
581 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot3_device_var
, tvb
, offset
);
582 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot3_device_var_classify
, tvb
, offset
);
583 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot3_units
, tvb
, offset
);
584 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot3_device_var_value
, tvb
, offset
);
585 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot3_device_var_status
, tvb
, offset
);
589 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot4_device_var
, tvb
, offset
);
590 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot4_device_var_classify
, tvb
, offset
);
591 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot4_units
, tvb
, offset
);
592 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot4_device_var_value
, tvb
, offset
);
593 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot4_device_var_status
, tvb
, offset
);
597 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot5_device_var
, tvb
, offset
);
598 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot5_device_var_classify
, tvb
, offset
);
599 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot5_units
, tvb
, offset
);
600 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot5_device_var_value
, tvb
, offset
);
601 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot5_device_var_status
, tvb
, offset
);
605 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot6_device_var
, tvb
, offset
);
606 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot6_device_var_classify
, tvb
, offset
);
607 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot6_units
, tvb
, offset
);
608 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot6_device_var_value
, tvb
, offset
);
609 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot6_device_var_status
, tvb
, offset
);
613 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot7_device_var
, tvb
, offset
);
614 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot7_device_var_classify
, tvb
, offset
);
615 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot7_units
, tvb
, offset
);
616 offset
+= dissect_float(body_tree
, hf_hartip_pt_rsp_slot7_device_var_value
, tvb
, offset
);
617 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_slot7_device_var_status
, tvb
, offset
);
620 dissect_timestamp(body_tree
, hf_hartip_pt_rsp_slot0_timestamp
, "Slot0 Data TimeStamp", 4, tvb
, offset
);
629 dissect_cmd13(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
632 offset
+= dissect_packAscii(body_tree
, hf_hartip_pt_rsp_tag
, "Tag", 6, tvb
, offset
);
633 offset
+= dissect_packAscii(body_tree
, hf_hartip_pt_rsp_packed_descriptor
, "descriptor", 12, tvb
, offset
);
634 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_day
, tvb
, offset
);
635 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_month
, tvb
, offset
);
636 /*offset += */dissect_byte(body_tree
, hf_hartip_pt_rsp_year
, tvb
, offset
);
645 dissect_cmd48(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
, gint bodylen
)
648 proto_tree_add_item(body_tree
, hf_hartip_pt_rsp_device_sp_status
, tvb
, offset
, 5, ENC_NA
);
650 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_extended_device_status
, tvb
, offset
);
651 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_device_op_mode
, tvb
, offset
);
652 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_standardized_status_0
, tvb
, offset
);
655 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_standardized_status_1
, tvb
, offset
);
656 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_analog_channel_saturated
, tvb
, offset
);
657 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_standardized_status_2
, tvb
, offset
);
658 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_standardized_status_3
, tvb
, offset
);
659 offset
+= dissect_byte(body_tree
, hf_hartip_pt_rsp_analog_channel_fixed
, tvb
, offset
);
663 proto_tree_add_item(body_tree
, hf_hartip_pt_rsp_device_sp_status
, tvb
, offset
, 11, ENC_NA
);
673 dissect_parse_hart_cmds(proto_tree
*body_tree
, tvbuff_t
*tvb
, guint8 cmd
,
674 gint offset
, gint bodylen
)
679 return dissect_cmd0(body_tree
, tvb
, offset
, bodylen
);
681 return dissect_cmd1(body_tree
, tvb
, offset
, bodylen
);
683 return dissect_cmd2(body_tree
, tvb
, offset
, bodylen
);
685 return dissect_cmd3(body_tree
, tvb
, offset
, bodylen
);
687 return dissect_cmd9(body_tree
, tvb
, offset
, bodylen
);
690 return dissect_packAscii(body_tree
, hf_hartip_pt_rsp_message
, "Message", 24, tvb
, offset
);
693 return dissect_cmd13(body_tree
, tvb
, offset
, bodylen
);
696 return dissect_string(body_tree
, hf_hartip_pt_rsp_tag
, "Tag", 32, tvb
, offset
);
699 return dissect_cmd48(body_tree
, tvb
, offset
, bodylen
);
706 dissect_pass_through(proto_tree
*body_tree
, tvbuff_t
*tvb
, gint offset
,
711 const char *frame_type_str
;
713 gint length
= bodylen
;
716 gint num_preambles
= 0;
719 /* find number of preambles */
720 while (length
> num_preambles
) {
721 delimiter
= tvb_get_guint8(tvb
, offset
+ num_preambles
);
722 if (delimiter
!= 0xFF)
728 if (num_preambles
> 0) {
729 proto_tree_add_item(body_tree
, hf_hartip_pt_preambles
, tvb
, offset
,
730 num_preambles
, ENC_NA
);
731 offset
+= num_preambles
;
732 length
-= num_preambles
;
736 delimiter
= tvb_get_guint8(tvb
, offset
);
737 ti
= proto_tree_add_uint(body_tree
, hf_hartip_pt_delimiter
, tvb
, offset
, 1,
742 if ((delimiter
& 0x7) == 2) {
743 frame_type_str
= "STX";
744 } else if ((delimiter
& 0x7) == 6) {
745 frame_type_str
= "ACK";
748 frame_type_str
= "UNK";
751 if ((delimiter
& 0x80) == 0) {
753 proto_item_set_text(ti
, "Short Address, Frame Type: %s", frame_type_str
);
755 proto_item_set_text(ti
, "Frame Type: %s", frame_type_str
);
761 proto_tree_add_item(body_tree
, hf_hartip_pt_short_addr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
767 proto_tree_add_item(body_tree
, hf_hartip_pt_long_addr
, tvb
, offset
, 5, ENC_NA
);
770 } else if (length
> 0) {
771 proto_tree_add_item(body_tree
, hf_hartip_data
, tvb
, offset
, length
, ENC_NA
);
777 cmd
= tvb_get_guint8(tvb
, offset
);
778 proto_tree_add_item(body_tree
, hf_hartip_pt_command
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
783 proto_tree_add_item(body_tree
, hf_hartip_pt_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
790 proto_tree_add_item(body_tree
, hf_hartip_pt_response_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
795 proto_tree_add_item(body_tree
, hf_hartip_pt_device_status
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
802 result
= dissect_parse_hart_cmds(body_tree
, tvb
, cmd
, offset
, length
);
804 proto_tree_add_item(body_tree
, hf_hartip_pt_payload
, tvb
, offset
,
805 (length
- 1), ENC_NA
);
807 offset
+= (length
- 1);
811 proto_tree_add_item(body_tree
, hf_hartip_pt_checksum
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
818 hartip_set_conversation(packet_info
*pinfo
)
820 conversation_t
*conversation
= NULL
;
822 if (!pinfo
->fd
->flags
.visited
&& (pinfo
->ptype
== PT_UDP
)) {
824 * This function is called for a session initiate send over UDP.
825 * The session initiate is sent to the server on port HARTIP_PORT.
826 * The server then responds from a different port. All subsequent
827 * communication for the session between the client and server
828 * uses the new server port and the original client port.
830 * A new conversation is created here and this dissector is set to
831 * be used for it. This allows the packets to be dissected properly
834 conversation
= find_conversation(pinfo
->fd
->num
,
835 &pinfo
->src
, &pinfo
->dst
, pinfo
->ptype
,
836 pinfo
->srcport
, 0, NO_PORT_B
);
837 if( (conversation
== NULL
) ||
838 (conversation
->dissector_handle
!= hartip_udp_handle
) ) {
839 conversation
= conversation_new(pinfo
->fd
->num
,
840 &pinfo
->src
, &pinfo
->dst
, pinfo
->ptype
,
841 pinfo
->srcport
, 0, NO_PORT2
);
842 conversation_set_dissector(conversation
, hartip_udp_handle
);
848 dissect_hartip_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
851 proto_tree
*hartip_tree
, *hdr_tree
, *body_tree
;
852 proto_item
*ti
, *hart_item
;
854 guint8 message_type
, message_id
;
855 guint16 transaction_id
, length
;
856 const char *msg_id_str
, *msg_type_str
;
857 hartip_tap_info
*tapinfo
;
859 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "HART_IP");
860 col_clear(pinfo
->cinfo
, COL_INFO
);
862 length
= tvb_get_ntohs(tvb
, offset
+6);
864 hart_item
= proto_tree_add_item(tree
, proto_hartip
, tvb
, 0, length
, ENC_NA
);
865 hartip_tree
= proto_item_add_subtree(hart_item
, ett_hartip
);
867 ti
= proto_tree_add_text(hartip_tree
, tvb
, offset
, HARTIP_HEADER_LENGTH
, "HART_IP Header");
868 hdr_tree
= proto_item_add_subtree(ti
, ett_hartip_hdr
);
870 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
873 message_type
= tvb_get_guint8(tvb
, offset
);
874 msg_type_str
= val_to_str(message_type
, hartip_message_type_values
, "Unknown message type %d");
875 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_message_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
878 message_id
= tvb_get_guint8(tvb
, offset
);
879 msg_id_str
= val_to_str(message_id
, hartip_message_id_values
, "Unknown message %d");
880 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_message_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
883 /* Setup statistics for tap. */
884 tapinfo
= wmem_new(wmem_packet_scope(), hartip_tap_info
);
885 tapinfo
->message_type
= message_type
;
886 tapinfo
->message_id
= message_id
;
887 tap_queue_packet(hartip_tap
, pinfo
, tapinfo
);
889 if (message_id
== SESSION_INITIATE_ID
) {
890 hartip_set_conversation(pinfo
);
893 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_status
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
896 transaction_id
= tvb_get_ntohs(tvb
, offset
);
897 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_transaction_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
900 proto_item_append_text(hart_item
, ", %s %s, Sequence Number %d", msg_id_str
,
901 msg_type_str
, transaction_id
);
903 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " | ",
904 "%s %s, Sequence Number %d",
905 msg_id_str
, msg_type_str
, transaction_id
);
906 col_set_fence(pinfo
->cinfo
, COL_INFO
);
908 proto_tree_add_item(hdr_tree
, hf_hartip_hdr_msg_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
911 if (length
< HARTIP_HEADER_LENGTH
)
912 return tvb_reported_length(tvb
);
913 bodylen
= length
- HARTIP_HEADER_LENGTH
;
915 /* add body elements. */
916 ti
= proto_tree_add_text(hartip_tree
, tvb
, offset
, bodylen
,
917 "HART_IP Body, %s, %s", msg_id_str
, msg_type_str
);
918 body_tree
= proto_item_add_subtree(ti
, ett_hartip_body
);
920 if (message_type
== ERROR_MSG_TYPE
) {
921 offset
+= dissect_error(body_tree
, tvb
, offset
, bodylen
);
923 /* Dissect the various HARTIP messages. */
925 case SESSION_INITIATE_ID
:
926 offset
+= dissect_session_init(body_tree
, tvb
, offset
, bodylen
);
928 case SESSION_CLOSE_ID
:
929 offset
+= dissect_session_close(body_tree
, pinfo
, tvb
, offset
, bodylen
);
932 offset
+= dissect_keep_alive(body_tree
, pinfo
, tvb
, offset
, bodylen
);
934 case PASS_THROUGH_ID
:
935 offset
+= dissect_pass_through(body_tree
, tvb
, offset
, bodylen
);
938 proto_tree_add_item(body_tree
, hf_hartip_data
, tvb
, offset
, bodylen
, ENC_NA
);
948 get_dissect_hartip_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
950 return tvb_get_ntohs(tvb
, offset
+6);
954 dissect_hartip_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
956 return dissect_hartip_common(tvb
, pinfo
, tree
, 0);
960 dissect_hartip_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
963 if (!tvb_bytes_exist(tvb
, 0, HARTIP_HEADER_LENGTH
))
966 tcp_dissect_pdus(tvb
, pinfo
, tree
, hartip_desegment
, HARTIP_HEADER_LENGTH
,
967 get_dissect_hartip_len
, dissect_hartip_pdu
, data
);
968 return tvb_reported_length(tvb
);
972 dissect_hartip_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
977 while (tvb_reported_length_remaining(tvb
, offset
) >= HARTIP_HEADER_LENGTH
)
978 offset
+= dissect_hartip_common(tvb
, pinfo
, tree
, offset
);
984 proto_register_hartip(void)
986 static hf_register_info hf
[] = {
987 /* HARTIP header elements. */
988 { &hf_hartip_hdr_version
,
989 { "Version", "hart_ip.version",
990 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
991 "HART_IP version number", HFILL
}
993 { &hf_hartip_hdr_message_type
,
994 { "Message Type", "hart_ip.message_type",
995 FT_UINT8
, BASE_DEC
, VALS(hartip_message_type_values
), 0,
996 "HART_IP message type", HFILL
}
998 { &hf_hartip_hdr_message_id
,
999 { "Message ID", "hart_ip.message_id",
1000 FT_UINT8
, BASE_DEC
, VALS(hartip_message_id_values
), 0,
1001 "HART_IP message id", HFILL
}
1003 { &hf_hartip_hdr_status
,
1004 { "Status", "hart_ip.status",
1005 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1006 "HART_IP status field", HFILL
}
1008 { &hf_hartip_hdr_transaction_id
,
1009 { "Sequence Number", "hart_ip.transaction_id",
1010 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1011 "HART_IP Sequence Number", HFILL
}
1013 { &hf_hartip_hdr_msg_length
,
1014 { "Message Length", "hart_ip.msg_length",
1015 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1016 "HART_IP Message Length", HFILL
}
1019 /* HARTIP Body elements */
1021 { "Message Data", "hart_ip.data",
1022 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1023 "HART_IP Message Data", HFILL
}
1025 { &hf_hartip_master_type
,
1026 { "Host Type", "hart_ip.session_init.master_type",
1027 FT_UINT8
, BASE_DEC
, VALS(hartip_master_type_values
), 0xFF,
1028 "Session Host Type", HFILL
}
1030 { &hf_hartip_inactivity_close_timer
,
1031 { "Inactivity Close Timer", "hart_ip.session_init.inactivity_close_timer",
1032 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1033 "Session Inactivity Close Timer", HFILL
}
1035 { &hf_hartip_error_code
,
1036 { "Error", "hart_ip.error.error_code",
1037 FT_UINT8
, BASE_DEC
, VALS(hartip_error_code_values
), 0xFF,
1038 "Error Code", HFILL
}
1041 /* HARTIP Pass-through commads. */
1042 { &hf_hartip_pt_preambles
,
1043 { "Preambles", "hart_ip.pt.preambles",
1044 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1045 "Pass Through Preambles", HFILL
}
1047 { &hf_hartip_pt_delimiter
,
1048 { "Delimter", "hart_ip.pt.delimter",
1049 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1050 "Pass Through Delimiter", HFILL
}
1052 { &hf_hartip_pt_short_addr
,
1053 { "Short Address", "hart_ip.pt.short_addr",
1054 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1055 "Pass Through Short Address", HFILL
}
1057 { &hf_hartip_pt_long_addr
,
1058 { "Long Address", "hart_ip.pt.long_address",
1059 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1060 "Pass Through Long Address", HFILL
}
1062 { &hf_hartip_pt_command
,
1063 { "Command", "hart_ip.pt.command",
1064 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1065 "Pass Through Command", HFILL
}
1067 { &hf_hartip_pt_length
,
1068 { "Length", "hart_ip.pt.length",
1069 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1070 "Pass Through Length", HFILL
}
1072 { &hf_hartip_pt_response_code
,
1073 { "Response Code", "hart_ip.pt.response_code",
1074 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1075 "Pass Through Response Code", HFILL
}
1077 { &hf_hartip_pt_device_status
,
1078 { "Device Status", "hart_ip.pt.device_status",
1079 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1080 "Pass Through Device Status", HFILL
}
1082 { &hf_hartip_pt_payload
,
1083 { "Payload", "hart_ip.pt.payload",
1084 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1085 "Pass Through Payload", HFILL
}
1087 { &hf_hartip_pt_checksum
,
1088 { "Checksum", "hart_ip.pt.checksum",
1089 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1090 "Pass Through Checksum", HFILL
}
1093 /* add fields for universal commands. */
1095 { &hf_hartip_pt_rsp_expansion_code
,
1096 { "Expansion Code", "hart_ip.pt.rsp.expansion_code",
1097 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1100 { &hf_hartip_pt_rsp_expanded_device_type
,
1101 { "Expanded Device Type", "hart_ip.pt.rsp.expanded_device_type",
1102 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1105 { &hf_hartip_pt_rsp_req_min_preambles
,
1106 { "Minimum Number of Request Preambles", "hart_ip.pt.rsp.req_min_preambles",
1107 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1110 { &hf_hartip_pt_rsp_hart_protocol_major_rev
,
1111 { "HART Universal Revision", "hart_ip.pt.rsp.hart_univ_rev",
1112 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1115 { &hf_hartip_pt_rsp_device_rev
,
1116 { "Device Revision", "hart_ip.pt.rsp.device_rev",
1117 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1120 { &hf_hartip_pt_rsp_software_rev
,
1121 { "Device Software Revision", "hart_ip.pt.rsp.software_rev",
1122 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1125 { &hf_hartip_pt_rsp_hardware_rev_physical_signal
,
1126 { "Hardware Rev and Physical Signaling", "hart_ip.pt.rsp.hardrev_and_physical_signal",
1127 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1130 { &hf_hartip_pt_rsp_flage
,
1131 { "Flags", "hart_ip.pt.rsp.flags",
1132 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1135 { &hf_hartip_pt_rsp_device_id
,
1136 { "Device ID", "hart_ip.pt.rsp.device_id",
1137 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1140 { &hf_hartip_pt_rsp_rsp_min_preambles
,
1141 { "Minimum Number of Response Preambles", "hart_ip.pt.rsp.rsp_min_preambles",
1142 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1145 { &hf_hartip_pt_rsp_max_device_variables
,
1146 { "Maximum Number of Device Variables", "hart_ip.pt.rsp.device_variables",
1147 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1150 { &hf_hartip_pt_rsp_configuration_change_counter
,
1151 { "Configuration Change Counter", "hart_ip.pt.rsp.configure_change",
1152 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1155 { &hf_hartip_pt_rsp_extended_device_status
,
1156 { "Extended Device Status", "hart_ip.pt.rsp.ext_device_status",
1157 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1160 { &hf_hartip_pt_rsp_manufacturer_Identification_code
,
1161 { "Manufacturer ID", "hart_ip.pt.rsp.manufacturer_Id",
1162 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1165 { &hf_hartip_pt_rsp_private_label
,
1166 { "Private Label", "hart_ip.pt.rsp.private_label",
1167 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1170 { &hf_hartip_pt_rsp_device_profile
,
1171 { "Device Profile", "hart_ip.pt.rsp.device_profile",
1172 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1177 { &hf_hartip_pt_rsp_pv_percent_range
,
1178 { "PV Percent Range", "hart_ip.pt.rsp.pv_percent_range",
1179 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1184 { &hf_hartip_pt_rsp_pv_loop_current
,
1185 { "PV Loop Current", "hart_ip.pt.rsp.pv_loop_current",
1186 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1189 { &hf_hartip_pt_rsp_pv_units
,
1190 { "PV Units", "hart_ip.pt.rsp.pv_units",
1191 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1194 { &hf_hartip_pt_rsp_pv
,
1195 { "PV", "hart_ip.pt.rsp.pv",
1196 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1199 { &hf_hartip_pt_rsp_sv_units
,
1200 { "SV Units", "hart_ip.pt.rsp.sv_units",
1201 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1204 { &hf_hartip_pt_rsp_sv
,
1205 { "SV", "hart_ip.pt.rsp.sv",
1206 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1209 { &hf_hartip_pt_rsp_tv_units
,
1210 { "TV Units", "hart_ip.pt.rsp.tv_units",
1211 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1214 { &hf_hartip_pt_rsp_tv
,
1215 { "TV", "hart_ip.pt.rsp.tv",
1216 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1219 { &hf_hartip_pt_rsp_qv_units
,
1220 { "QV Units", "hart_ip.pt.rsp.qv_units",
1221 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1224 { &hf_hartip_pt_rsp_qv
,
1225 { "QV", "hart_ip.pt.rsp.qv",
1226 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1231 { &hf_hartip_pt_rsp_slot0_device_var
,
1232 { "Slot0 Device Variable", "hart_ip.pt.rsp.slot0_device_var",
1233 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1236 { &hf_hartip_pt_rsp_slot0_device_var_classify
,
1237 { "Slot0 Device Variable Classification", "hart_ip.pt.rsp.slot0_device_var_classify",
1238 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1241 { &hf_hartip_pt_rsp_slot0_units
,
1242 { "Slot0 Units", "hart_ip.pt.rsp.slot0_units",
1243 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1246 { &hf_hartip_pt_rsp_slot0_device_var_value
,
1247 { "Slot0 Device Variable Value", "hart_ip.pt.rsp.slot0_device_var_value",
1248 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1251 { &hf_hartip_pt_rsp_slot0_device_var_status
,
1252 { "Slot0 Device Variable Status", "hart_ip.pt.rsp.slot0_device_var_status",
1253 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1256 { &hf_hartip_pt_rsp_slot1_device_var
,
1257 { "Slot1 Device Variable", "hart_ip.pt.rsp.slot1_device_var",
1258 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1261 { &hf_hartip_pt_rsp_slot1_device_var_classify
,
1262 { "Slot1 Device Variable Classification", "hart_ip.pt.rsp.slot1_device_var_classify",
1263 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1266 { &hf_hartip_pt_rsp_slot1_units
,
1267 { "Slot1 Units", "hart_ip.pt.rsp.slot1_units",
1268 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1271 { &hf_hartip_pt_rsp_slot1_device_var_value
,
1272 { "Slot1 Device Variable Value", "hart_ip.pt.rsp.slot1_device_var_value",
1273 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1276 { &hf_hartip_pt_rsp_slot1_device_var_status
,
1277 { "Slot1 Device Variable Status", "hart_ip.pt.rsp.slot1_device_var_status",
1278 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1281 { &hf_hartip_pt_rsp_slot2_device_var
,
1282 { "Slot2 Device Variable", "hart_ip.pt.rsp.slot2_device_var",
1283 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1286 { &hf_hartip_pt_rsp_slot2_device_var_classify
,
1287 { "Slot2 Device Variable Classification", "hart_ip.pt.rsp.slot2_device_var_classify",
1288 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1291 { &hf_hartip_pt_rsp_slot2_units
,
1292 { "Slot2 Units", "hart_ip.pt.rsp.slot2_units",
1293 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1296 { &hf_hartip_pt_rsp_slot2_device_var_value
,
1297 { "Slot2 Device Variable Value", "hart_ip.pt.rsp.slot2_device_var_value",
1298 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1301 { &hf_hartip_pt_rsp_slot2_device_var_status
,
1302 { "Slot2 Device Variable Status", "hart_ip.pt.rsp.slot2_device_var_status",
1303 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1306 { &hf_hartip_pt_rsp_slot3_device_var
,
1307 { "Slot3 Device Variable", "hart_ip.pt.rsp.slot3_device_var",
1308 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1311 { &hf_hartip_pt_rsp_slot3_device_var_classify
,
1312 { "Slot3 Device Variable Classification", "hart_ip.pt.rsp.slot3_device_var_classify",
1313 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1316 { &hf_hartip_pt_rsp_slot3_units
,
1317 { "Slot3 Units", "hart_ip.pt.rsp.slot3_units",
1318 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1321 { &hf_hartip_pt_rsp_slot3_device_var_value
,
1322 { "Slot3 Device Variable Value", "hart_ip.pt.rsp.slot3_device_var_value",
1323 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1326 { &hf_hartip_pt_rsp_slot3_device_var_status
,
1327 { "Slot3 Device Variable Status", "hart_ip.pt.rsp.slot3_device_var_status",
1328 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1331 { &hf_hartip_pt_rsp_slot4_device_var
,
1332 { "Slot4 Device Variable", "hart_ip.pt.rsp.slot4_device_var",
1333 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1336 { &hf_hartip_pt_rsp_slot4_device_var_classify
,
1337 { "Slot4 Device Variable Classification", "hart_ip.pt.rsp.slot4_device_var_classify",
1338 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1341 { &hf_hartip_pt_rsp_slot4_units
,
1342 { "Slot4 Units", "hart_ip.pt.rsp.slot4_units",
1343 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1346 { &hf_hartip_pt_rsp_slot4_device_var_value
,
1347 { "Slot4 Device Variable Value", "hart_ip.pt.rsp.slot4_device_var_value",
1348 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1351 { &hf_hartip_pt_rsp_slot4_device_var_status
,
1352 { "Slot4 Device Variable Status", "hart_ip.pt.rsp.slot4_device_var_status",
1353 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1356 { &hf_hartip_pt_rsp_slot5_device_var
,
1357 { "Slot5 Device Variable", "hart_ip.pt.rsp.slot5_device_var",
1358 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1361 { &hf_hartip_pt_rsp_slot5_device_var_classify
,
1362 { "Slot5 Device Variable Classification", "hart_ip.pt.rsp.slot5_device_var_classify",
1363 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1366 { &hf_hartip_pt_rsp_slot5_units
,
1367 { "Slot5 Units", "hart_ip.pt.rsp.slot5_units",
1368 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1371 { &hf_hartip_pt_rsp_slot5_device_var_value
,
1372 { "Slot5 Device Variable Value", "hart_ip.pt.rsp.slot5_device_var_value",
1373 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1376 { &hf_hartip_pt_rsp_slot5_device_var_status
,
1377 { "Slot5 Device Variable Status", "hart_ip.pt.rsp.slot5_device_var_status",
1378 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1381 { &hf_hartip_pt_rsp_slot6_device_var
,
1382 { "Slot6 Device Variable", "hart_ip.pt.rsp.slot6_device_var",
1383 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1386 { &hf_hartip_pt_rsp_slot6_device_var_classify
,
1387 { "Slot6 Device Variable Classification", "hart_ip.pt.rsp.slot6_device_var_classify",
1388 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1391 { &hf_hartip_pt_rsp_slot6_units
,
1392 { "Slot6 Units", "hart_ip.pt.rsp.slot6_units",
1393 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1396 { &hf_hartip_pt_rsp_slot6_device_var_value
,
1397 { "Slot6 Device Variable Value", "hart_ip.pt.rsp.slot6_device_var_value",
1398 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1401 { &hf_hartip_pt_rsp_slot6_device_var_status
,
1402 { "Slot6 Device Variable Status", "hart_ip.pt.rsp.slot6_device_var_status",
1403 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1406 { &hf_hartip_pt_rsp_slot7_device_var
,
1407 { "Slot7 Device Variable", "hart_ip.pt.rsp.slot7_device_var",
1408 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1411 { &hf_hartip_pt_rsp_slot7_device_var_classify
,
1412 { "Slot7 Device Variable Classification", "hart_ip.pt.rsp.slot7_device_var_classify",
1413 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1416 { &hf_hartip_pt_rsp_slot7_units
,
1417 { "Slot7 Units", "hart_ip.pt.rsp.slot7_units",
1418 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1421 { &hf_hartip_pt_rsp_slot7_device_var_value
,
1422 { "Slot7 Device Variable Value", "hart_ip.pt.rsp.slot7_device_var_value",
1423 FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
1426 { &hf_hartip_pt_rsp_slot7_device_var_status
,
1427 { "Slot7 Device Variable Status", "hart_ip.pt.rsp.slot7_device_var_status",
1428 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1431 { &hf_hartip_pt_rsp_slot0_timestamp
,
1432 { "Slot0 Data TimeStamp", "hart_ip.pt.rsp.slot0_data_timestamp",
1433 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1438 { &hf_hartip_pt_rsp_packed_descriptor
,
1439 { "Descriptor", "hart_ip.pt.rsp.descriptor",
1440 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1443 { &hf_hartip_pt_rsp_day
,
1444 { "Day", "hart_ip.pt.rsp.day",
1445 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1448 { &hf_hartip_pt_rsp_month
,
1449 { "Month", "hart_ip.pt.rsp.month",
1450 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1453 { &hf_hartip_pt_rsp_year
,
1454 { "Year", "hart_ip.pt.rsp.year",
1455 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1460 { &hf_hartip_pt_rsp_tag
,
1461 { "Tag", "hart_ip.pt.rsp.tag",
1462 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1467 { &hf_hartip_pt_rsp_message
,
1468 { "Message", "hart_ip.pt.rsp.message",
1469 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1474 { &hf_hartip_pt_rsp_device_sp_status
,
1475 { "Device-Specific Status", "hart_ip.pt.rsp.device_sp_status",
1476 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1479 { &hf_hartip_pt_rsp_device_op_mode
,
1480 { "Device Operating Mode", "hart_ip.pt.rsp.device_op_mode",
1481 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1484 { &hf_hartip_pt_rsp_standardized_status_0
,
1485 { "Standardized Status 0", "hart_ip.pt.rsp.standardized_status_0",
1486 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1489 { &hf_hartip_pt_rsp_standardized_status_1
,
1490 { "Standardized Status 1", "hart_ip.pt.rsp.standardized_status_1",
1491 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1494 { &hf_hartip_pt_rsp_analog_channel_saturated
,
1495 { "Analog Channel Saturated", "hart_ip.pt.rsp.analog_channel_saturated",
1496 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1499 { &hf_hartip_pt_rsp_standardized_status_2
,
1500 { "Standardized Status 2", "hart_ip.pt.rsp.standardized_status_2",
1501 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1504 { &hf_hartip_pt_rsp_standardized_status_3
,
1505 { "Standardized Status 3", "hart_ip.pt.rsp.standardized_status_3",
1506 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1509 { &hf_hartip_pt_rsp_analog_channel_fixed
,
1510 { "Analog Channel Fixed", "hart_ip.pt.rsp.analog_channel_fixed",
1511 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1517 static gint
*ett
[] = {
1523 static ei_register_info ei
[] = {
1524 { &ei_hartip_data_none
, { "hart_ip.data.none", PI_PROTOCOL
, PI_NOTE
, "No data", EXPFILL
}},
1525 { &ei_hartip_data_unexpected
, { "hart_ip.data.unexpected", PI_PROTOCOL
, PI_WARN
, "Unexpected message body", EXPFILL
}},
1528 module_t
*hartip_module
;
1529 expert_module_t
* expert_hartip
;
1531 proto_hartip
= proto_register_protocol("HART_IP Protocol", "HART_IP", "hart_ip");
1532 proto_register_field_array(proto_hartip
, hf
, array_length(hf
));
1533 proto_register_subtree_array(ett
, array_length(ett
));
1534 expert_hartip
= expert_register_protocol(proto_hartip
);
1535 expert_register_field_array(expert_hartip
, ei
, array_length(ei
));
1537 hartip_module
= prefs_register_protocol(proto_hartip
, NULL
);
1538 prefs_register_bool_preference(hartip_module
, "desegment",
1539 "Desegment all HART-IP messages spanning multiple TCP segments",
1540 "Whether the HART-IP dissector should desegment all messages spanning multiple TCP segments",
1543 hartip_tap
= register_tap("hart_ip");
1547 proto_reg_handoff_hartip(void)
1549 hartip_tcp_handle
= new_create_dissector_handle(dissect_hartip_tcp
, proto_hartip
);
1550 hartip_udp_handle
= new_create_dissector_handle(dissect_hartip_udp
, proto_hartip
);
1551 dissector_add_uint("udp.port", HARTIP_PORT
, hartip_udp_handle
);
1552 dissector_add_uint("tcp.port", HARTIP_PORT
, hartip_tcp_handle
);
1554 stats_tree_register("hart_ip", "hart_ip", "HART-IP", 0,
1555 hartip_stats_tree_packet
, hartip_stats_tree_init
, NULL
);
1559 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1564 * indent-tabs-mode: nil
1567 * vi: set shiftwidth=2 tabstop=2 expandtab:
1568 * :indentSize=2:tabSize=2:noTabs=true: