HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-hartip.c
blob7aab582c579b86bf966a4bcd245bf75cc0235cce
1 /* packet-hartip.c
2 * Routines for HART-IP packet dissection
3 * Copyright 2012, Bill Schiller <bill.schiller@emerson.com>
5 * $Id$
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.
28 #include "config.h"
29 #include <glib.h>
30 #include <epan/conversation.h>
31 #include <epan/packet.h>
32 #include <epan/tap.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;
164 /* response Tag */
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
183 /* HARTIP header */
184 typedef struct _hartip_hdr {
185 guint8 version;
186 guint8 message_type;
187 guint8 message_id;
188 guint8 status;
189 guint16 transaction_id;
190 guint16 length;
191 } hartip_hdr;
193 /* Message IDs */
194 #define SESSION_INITIATE_ID 0
195 #define SESSION_CLOSE_ID 1
196 #define KEEP_ALIVE_ID 2
197 #define PASS_THROUGH_ID 3
199 /* Message types */
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" },
209 { 0, NULL }
212 static const value_string hartip_message_type_values[] = {
213 { REQUEST_MSG_TYPE, "Request" },
214 { RESPONSE_MSG_TYPE, "Response" },
215 { ERROR_MSG_TYPE, "Error" },
216 { 0, NULL }
219 /* Host types */
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" },
226 { 0, NULL }
229 /* Error Codes */
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" },
238 { 0, NULL }
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 {
246 gint8 message_type;
247 gint8 message_id;
248 } 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;
262 static void
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);
271 static int
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;
283 break;
284 case RESPONSE_MSG_TYPE:
285 message_type_node_str = st_str_responses;
286 message_type_node = st_node_responses;
287 break;
288 case ERROR_MSG_TYPE:
289 message_type_node_str = st_str_errors;
290 message_type_node = st_node_errors;
291 break;
292 default:
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);
304 return 1;
307 static gint
308 dissect_empty_body(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb,
309 gint offset, gint bodylen)
311 proto_item *ti;
313 ti = proto_tree_add_item(tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
314 if (bodylen == 0) {
315 expert_add_info(pinfo, ti, &ei_hartip_data_none);
316 } else {
317 expert_add_info(pinfo, ti, &ei_hartip_data_unexpected);
319 return bodylen;
322 static gint
323 dissect_session_init(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
324 gint bodylen)
326 if (bodylen == 5) {
327 proto_tree_add_item(body_tree, hf_hartip_master_type, tvb, offset, 1, ENC_BIG_ENDIAN);
328 offset++;
330 proto_tree_add_item(body_tree, hf_hartip_inactivity_close_timer, tvb, offset, 4, ENC_BIG_ENDIAN);
331 } else {
332 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
335 return bodylen;
338 static gint
339 dissect_error(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
341 if (bodylen == 1) {
342 proto_tree_add_item(body_tree, hf_hartip_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
343 } else {
344 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
347 return bodylen;
350 static gint
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);
357 static gint
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);
364 static gint
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);
368 return 1;
371 static gint
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);
375 return 2;
378 static gint
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);
382 return 4;
385 static gint
386 dissect_string(proto_tree *tree, int hf, const char *name, int len,
387 tvbuff_t *tvb, gint offset)
389 proto_item *ti;
390 char *str;
392 str = (char *)wmem_alloc(wmem_packet_scope(), 256);
394 ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA);
395 if (len < 256) {
396 (void) tvb_get_nstringz0(tvb, offset, len + 1, str);
397 proto_item_set_text(ti, "%s: %s", name, str);
400 return len;
403 static gint
404 dissect_packAscii(proto_tree *tree, int hf, const char *name, int len,
405 tvbuff_t *tvb, gint offset)
407 gushort usIdx;
408 gushort usGroupCnt;
409 gushort usMaxGroups; /* Number of 4 byte groups to pack. */
410 gushort usMask;
411 gint iIndex;
412 gint i = 0;
413 proto_item *ti;
414 gushort buf[4];
415 guint8 *tmp;
416 char *str = NULL;
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);
426 iIndex = 0;
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);
436 iIndex += 3;
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);
447 str[i] = '\0';
448 proto_item_set_text(ti, "%s: %s", name, str);
450 return len;
453 static gint
454 dissect_timestamp(proto_tree *tree, int hf, const char *name, int len,
455 tvbuff_t *tvb, gint offset)
457 proto_item *ti;
458 guint32 t;
459 guint32 hrs = 0;
460 guint32 mins = 0;
461 guint32 secs = 0;
462 guint32 ms = 0;
464 ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA);
465 t = tvb_get_ntohl(tvb, offset);
467 if (t > 0 ) {
468 t /= 32;
469 ms = t % 1000;
470 t /= 1000;
471 secs = t % 60;
472 t /= 60;
473 mins = t % 60;
474 hrs = (guint)(t / 60);
477 proto_item_set_text(ti, "%s: %02d:%02d:%02d.%03d", name, hrs, mins, secs, ms);
478 return len;
481 static gint
482 dissect_cmd0(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
484 if (bodylen >= 22) {
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);
494 offset += 3;
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);
503 return bodylen;
506 return 0;
509 static gint
510 dissect_cmd1(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
512 if (bodylen >= 5) {
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);
515 return bodylen;
518 return 0;
521 static gint
522 dissect_cmd2(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
524 if (bodylen >= 8) {
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);
527 return bodylen;
530 return 0;
533 static gint
534 dissect_cmd3(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
536 if (bodylen >= 24) {
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);
547 return bodylen;
550 return 0;
553 static gint
554 dissect_cmd9(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
556 if (bodylen >= 14) {
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);
564 if (bodylen >= 22) {
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);
572 if (bodylen >= 30) {
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);
580 if (bodylen >= 38) {
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);
588 if (bodylen >= 46) {
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);
596 if (bodylen >= 54) {
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);
604 if (bodylen >= 62) {
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);
612 if (bodylen >= 70) {
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);
622 return bodylen;
625 return 0;
628 static gint
629 dissect_cmd13(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
631 if (bodylen >= 21) {
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);
638 return bodylen;
641 return 0;
644 static gint
645 dissect_cmd48(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
647 if (bodylen >= 9) {
648 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 5, ENC_NA);
649 offset += 5;
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);
654 if (bodylen >= 14) {
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);
662 if (bodylen >= 24) {
663 proto_tree_add_item(body_tree, hf_hartip_pt_rsp_device_sp_status, tvb, offset, 11, ENC_NA);
664 /*offset += 11;*/
666 return bodylen;
669 return 0;
672 static gint
673 dissect_parse_hart_cmds(proto_tree *body_tree, tvbuff_t *tvb, guint8 cmd,
674 gint offset, gint bodylen)
676 switch(cmd)
678 case 0:
679 return dissect_cmd0(body_tree, tvb, offset, bodylen);
680 case 1:
681 return dissect_cmd1(body_tree, tvb, offset, bodylen);
682 case 2:
683 return dissect_cmd2(body_tree, tvb, offset, bodylen);
684 case 3:
685 return dissect_cmd3(body_tree, tvb, offset, bodylen);
686 case 9:
687 return dissect_cmd9(body_tree, tvb, offset, bodylen);
688 case 12:
689 if (bodylen >= 24)
690 return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, "Message", 24, tvb, offset);
691 break;
692 case 13:
693 return dissect_cmd13(body_tree, tvb, offset, bodylen);
694 case 20:
695 if (bodylen >= 32)
696 return dissect_string(body_tree, hf_hartip_pt_rsp_tag, "Tag", 32, tvb, offset);
697 break;
698 case 48:
699 return dissect_cmd48(body_tree, tvb, offset, bodylen);
702 return 0;
705 static gint
706 dissect_pass_through(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
707 gint bodylen)
709 proto_item *ti;
710 guint8 delimiter;
711 const char *frame_type_str;
712 guint8 cmd = 0;
713 gint length = bodylen;
714 gint is_short = 0;
715 gint is_rsp = 0;
716 gint num_preambles = 0;
717 gint result;
719 /* find number of preambles */
720 while (length > num_preambles) {
721 delimiter = tvb_get_guint8(tvb, offset + num_preambles);
722 if (delimiter != 0xFF)
723 break;
725 num_preambles += 1;
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;
735 if (length > 0) {
736 delimiter = tvb_get_guint8(tvb, offset);
737 ti = proto_tree_add_uint(body_tree, hf_hartip_pt_delimiter, tvb, offset, 1,
738 delimiter);
739 offset++;
740 length--;
742 if ((delimiter & 0x7) == 2) {
743 frame_type_str = "STX";
744 } else if ((delimiter & 0x7) == 6) {
745 frame_type_str = "ACK";
746 is_rsp = 1;
747 } else {
748 frame_type_str = "UNK";
751 if ((delimiter & 0x80) == 0) {
752 is_short = 1;
753 proto_item_set_text(ti, "Short Address, Frame Type: %s", frame_type_str);
754 } else {
755 proto_item_set_text(ti, "Frame Type: %s", frame_type_str);
759 if (is_short == 1) {
760 if (length > 0) {
761 proto_tree_add_item(body_tree, hf_hartip_pt_short_addr, tvb, offset, 1, ENC_BIG_ENDIAN);
762 offset++;
763 length--;
765 } else {
766 if (length > 4) {
767 proto_tree_add_item(body_tree, hf_hartip_pt_long_addr, tvb, offset, 5, ENC_NA);
768 offset += 5;
769 length -= 5;
770 } else if (length > 0) {
771 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, length, ENC_NA);
772 length = 0;
776 if (length > 0) {
777 cmd = tvb_get_guint8(tvb, offset);
778 proto_tree_add_item(body_tree, hf_hartip_pt_command, tvb, offset, 1, ENC_BIG_ENDIAN);
779 offset++;
780 length--;
782 if (length > 0) {
783 proto_tree_add_item(body_tree, hf_hartip_pt_length, tvb, offset, 1, ENC_BIG_ENDIAN);
784 offset++;
785 length--;
788 if (is_rsp == 1) {
789 if (length > 0) {
790 proto_tree_add_item(body_tree, hf_hartip_pt_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
791 offset++;
792 length--;
794 if (length > 0) {
795 proto_tree_add_item(body_tree, hf_hartip_pt_device_status, tvb, offset, 1, ENC_BIG_ENDIAN);
796 offset++;
797 length--;
801 if (length > 1) {
802 result = dissect_parse_hart_cmds(body_tree, tvb, cmd, offset, length);
803 if (result == 0 ) {
804 proto_tree_add_item(body_tree, hf_hartip_pt_payload, tvb, offset,
805 (length - 1), ENC_NA);
807 offset += (length - 1);
808 length = 1;
810 if (length > 0) {
811 proto_tree_add_item(body_tree, hf_hartip_pt_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
814 return bodylen;
817 static void
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
832 * for this protocol.
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);
847 static int
848 dissect_hartip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
849 gint offset)
851 proto_tree *hartip_tree, *hdr_tree, *body_tree;
852 proto_item *ti, *hart_item;
853 gint bodylen;
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);
871 offset++;
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);
876 offset++;
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);
881 offset++;
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);
894 offset++;
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);
898 offset += 2;
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);
909 offset += 2;
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);
922 } else {
923 /* Dissect the various HARTIP messages. */
924 switch(message_id) {
925 case SESSION_INITIATE_ID:
926 offset += dissect_session_init(body_tree, tvb, offset, bodylen);
927 break;
928 case SESSION_CLOSE_ID:
929 offset += dissect_session_close(body_tree, pinfo, tvb, offset, bodylen);
930 break;
931 case KEEP_ALIVE_ID:
932 offset += dissect_keep_alive(body_tree, pinfo, tvb, offset, bodylen);
933 break;
934 case PASS_THROUGH_ID:
935 offset += dissect_pass_through(body_tree, tvb, offset, bodylen);
936 break;
937 default:
938 proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
939 offset += bodylen;
940 break;
944 return offset;
947 static guint
948 get_dissect_hartip_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
950 return tvb_get_ntohs(tvb, offset+6);
953 static int
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);
959 static int
960 dissect_hartip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
961 void *data)
963 if (!tvb_bytes_exist(tvb, 0, HARTIP_HEADER_LENGTH))
964 return 0;
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);
971 static int
972 dissect_hartip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
973 void *data _U_)
975 gint offset = 0;
977 while (tvb_reported_length_remaining(tvb, offset) >= HARTIP_HEADER_LENGTH)
978 offset += dissect_hartip_common(tvb, pinfo, tree, offset);
980 return offset;
983 void
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 */
1020 { &hf_hartip_data,
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. */
1094 /* command 0 */
1095 { &hf_hartip_pt_rsp_expansion_code,
1096 { "Expansion Code", "hart_ip.pt.rsp.expansion_code",
1097 FT_UINT8, BASE_DEC, NULL, 0x0,
1098 NULL, HFILL }
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,
1103 NULL, HFILL }
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,
1108 NULL, HFILL }
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,
1113 NULL, HFILL }
1115 { &hf_hartip_pt_rsp_device_rev,
1116 { "Device Revision", "hart_ip.pt.rsp.device_rev",
1117 FT_UINT8, BASE_DEC, NULL, 0x0,
1118 NULL, HFILL }
1120 { &hf_hartip_pt_rsp_software_rev,
1121 { "Device Software Revision", "hart_ip.pt.rsp.software_rev",
1122 FT_UINT8, BASE_DEC, NULL, 0x0,
1123 NULL, HFILL }
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,
1128 NULL, HFILL }
1130 { &hf_hartip_pt_rsp_flage,
1131 { "Flags", "hart_ip.pt.rsp.flags",
1132 FT_UINT8, BASE_HEX, NULL, 0x0,
1133 NULL, HFILL }
1135 { &hf_hartip_pt_rsp_device_id,
1136 { "Device ID", "hart_ip.pt.rsp.device_id",
1137 FT_BYTES, BASE_NONE, NULL, 0x0,
1138 NULL, HFILL }
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,
1143 NULL, HFILL }
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,
1148 NULL, HFILL }
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,
1153 NULL, HFILL }
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,
1158 NULL, HFILL }
1160 { &hf_hartip_pt_rsp_manufacturer_Identification_code,
1161 { "Manufacturer ID", "hart_ip.pt.rsp.manufacturer_Id",
1162 FT_UINT16, BASE_DEC, NULL, 0x0,
1163 NULL, HFILL }
1165 { &hf_hartip_pt_rsp_private_label,
1166 { "Private Label", "hart_ip.pt.rsp.private_label",
1167 FT_UINT16, BASE_DEC, NULL, 0x0,
1168 NULL, HFILL }
1170 { &hf_hartip_pt_rsp_device_profile,
1171 { "Device Profile", "hart_ip.pt.rsp.device_profile",
1172 FT_UINT8, BASE_DEC, NULL, 0x0,
1173 NULL, HFILL }
1176 /* command 2 */
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,
1180 NULL, HFILL }
1183 /* command 3 */
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,
1187 NULL, HFILL }
1189 { &hf_hartip_pt_rsp_pv_units,
1190 { "PV Units", "hart_ip.pt.rsp.pv_units",
1191 FT_UINT8, BASE_DEC, NULL, 0x0,
1192 NULL, HFILL }
1194 { &hf_hartip_pt_rsp_pv,
1195 { "PV", "hart_ip.pt.rsp.pv",
1196 FT_FLOAT, BASE_NONE, NULL, 0x0,
1197 NULL, HFILL }
1199 { &hf_hartip_pt_rsp_sv_units,
1200 { "SV Units", "hart_ip.pt.rsp.sv_units",
1201 FT_UINT8, BASE_DEC, NULL, 0x0,
1202 NULL, HFILL }
1204 { &hf_hartip_pt_rsp_sv,
1205 { "SV", "hart_ip.pt.rsp.sv",
1206 FT_FLOAT, BASE_NONE, NULL, 0x0,
1207 NULL, HFILL }
1209 { &hf_hartip_pt_rsp_tv_units,
1210 { "TV Units", "hart_ip.pt.rsp.tv_units",
1211 FT_UINT8, BASE_DEC, NULL, 0x0,
1212 NULL, HFILL }
1214 { &hf_hartip_pt_rsp_tv,
1215 { "TV", "hart_ip.pt.rsp.tv",
1216 FT_FLOAT, BASE_NONE, NULL, 0x0,
1217 NULL, HFILL }
1219 { &hf_hartip_pt_rsp_qv_units,
1220 { "QV Units", "hart_ip.pt.rsp.qv_units",
1221 FT_UINT8, BASE_DEC, NULL, 0x0,
1222 NULL, HFILL }
1224 { &hf_hartip_pt_rsp_qv,
1225 { "QV", "hart_ip.pt.rsp.qv",
1226 FT_FLOAT, BASE_NONE, NULL, 0x0,
1227 NULL, HFILL }
1230 /* command 9 */
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,
1234 NULL, HFILL }
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,
1239 NULL, HFILL }
1241 { &hf_hartip_pt_rsp_slot0_units,
1242 { "Slot0 Units", "hart_ip.pt.rsp.slot0_units",
1243 FT_UINT8, BASE_DEC, NULL, 0x0,
1244 NULL, HFILL }
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,
1249 NULL, HFILL }
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,
1254 NULL, HFILL }
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,
1259 NULL, HFILL }
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,
1264 NULL, HFILL }
1266 { &hf_hartip_pt_rsp_slot1_units,
1267 { "Slot1 Units", "hart_ip.pt.rsp.slot1_units",
1268 FT_UINT8, BASE_DEC, NULL, 0x0,
1269 NULL, HFILL }
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,
1274 NULL, HFILL }
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,
1279 NULL, HFILL }
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,
1284 NULL, HFILL }
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,
1289 NULL, HFILL }
1291 { &hf_hartip_pt_rsp_slot2_units,
1292 { "Slot2 Units", "hart_ip.pt.rsp.slot2_units",
1293 FT_UINT8, BASE_DEC, NULL, 0x0,
1294 NULL, HFILL }
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,
1299 NULL, HFILL }
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,
1304 NULL, HFILL }
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,
1309 NULL, HFILL }
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,
1314 NULL, HFILL }
1316 { &hf_hartip_pt_rsp_slot3_units,
1317 { "Slot3 Units", "hart_ip.pt.rsp.slot3_units",
1318 FT_UINT8, BASE_DEC, NULL, 0x0,
1319 NULL, HFILL }
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,
1324 NULL, HFILL }
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,
1329 NULL, HFILL }
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,
1334 NULL, HFILL }
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,
1339 NULL, HFILL }
1341 { &hf_hartip_pt_rsp_slot4_units,
1342 { "Slot4 Units", "hart_ip.pt.rsp.slot4_units",
1343 FT_UINT8, BASE_DEC, NULL, 0x0,
1344 NULL, HFILL }
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,
1349 NULL, HFILL }
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,
1354 NULL, HFILL }
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,
1359 NULL, HFILL }
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,
1364 NULL, HFILL }
1366 { &hf_hartip_pt_rsp_slot5_units,
1367 { "Slot5 Units", "hart_ip.pt.rsp.slot5_units",
1368 FT_UINT8, BASE_DEC, NULL, 0x0,
1369 NULL, HFILL }
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,
1374 NULL, HFILL }
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,
1379 NULL, HFILL }
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,
1384 NULL, HFILL }
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,
1389 NULL, HFILL }
1391 { &hf_hartip_pt_rsp_slot6_units,
1392 { "Slot6 Units", "hart_ip.pt.rsp.slot6_units",
1393 FT_UINT8, BASE_DEC, NULL, 0x0,
1394 NULL, HFILL }
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,
1399 NULL, HFILL }
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,
1404 NULL, HFILL }
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,
1409 NULL, HFILL }
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,
1414 NULL, HFILL }
1416 { &hf_hartip_pt_rsp_slot7_units,
1417 { "Slot7 Units", "hart_ip.pt.rsp.slot7_units",
1418 FT_UINT8, BASE_DEC, NULL, 0x0,
1419 NULL, HFILL }
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,
1424 NULL, HFILL }
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,
1429 NULL, HFILL }
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,
1434 NULL, HFILL }
1437 /* command 13 */
1438 { &hf_hartip_pt_rsp_packed_descriptor,
1439 { "Descriptor", "hart_ip.pt.rsp.descriptor",
1440 FT_BYTES, BASE_NONE, NULL, 0x0,
1441 NULL, HFILL }
1443 { &hf_hartip_pt_rsp_day,
1444 { "Day", "hart_ip.pt.rsp.day",
1445 FT_UINT8, BASE_DEC, NULL, 0x0,
1446 NULL, HFILL }
1448 { &hf_hartip_pt_rsp_month,
1449 { "Month", "hart_ip.pt.rsp.month",
1450 FT_UINT8, BASE_DEC, NULL, 0x0,
1451 NULL, HFILL }
1453 { &hf_hartip_pt_rsp_year,
1454 { "Year", "hart_ip.pt.rsp.year",
1455 FT_UINT8, BASE_DEC, NULL, 0x0,
1456 NULL, HFILL }
1459 /* Tag */
1460 { &hf_hartip_pt_rsp_tag,
1461 { "Tag", "hart_ip.pt.rsp.tag",
1462 FT_BYTES, BASE_NONE, NULL, 0x0,
1463 NULL, HFILL }
1466 /* Message */
1467 { &hf_hartip_pt_rsp_message,
1468 { "Message", "hart_ip.pt.rsp.message",
1469 FT_BYTES, BASE_NONE, NULL, 0x0,
1470 NULL, HFILL }
1473 /* command 48 */
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,
1477 NULL, HFILL }
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,
1482 NULL, HFILL }
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,
1487 NULL, HFILL }
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,
1492 NULL, HFILL }
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,
1497 NULL, HFILL }
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,
1502 NULL, HFILL }
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,
1507 NULL, HFILL }
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,
1512 NULL, HFILL
1517 static gint *ett[] = {
1518 &ett_hartip,
1519 &ett_hartip_hdr,
1520 &ett_hartip_body
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",
1541 &hartip_desegment);
1543 hartip_tap = register_tap("hart_ip");
1546 void
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
1561 * Local variables:
1562 * c-basic-offset: 2
1563 * tab-width: 2
1564 * indent-tabs-mode: nil
1565 * End:
1567 * vi: set shiftwidth=2 tabstop=2 expandtab:
1568 * :indentSize=2:tabSize=2:noTabs=true: