HTTPS (almost) everywhere.
[metze/wireshark/wip.git] / epan / dissectors / packet-hartip.c
1 /* packet-hartip.c
2  * Routines for HART-IP packet dissection
3  * Copyright 2012, Bill Schiller <bill.schiller@emerson.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Copied from packet-mbtcp.c
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13
14 #include "config.h"
15
16 #include <epan/packet.h>
17 #include <epan/stats_tree.h>
18 #include <epan/expert.h>
19 #include <epan/prefs.h>
20 #include "packet-tcp.h"
21
22 void proto_register_hartip(void);
23 void proto_reg_handoff_hartip(void);
24
25 static dissector_handle_t hartip_tcp_handle;
26 static dissector_handle_t hartip_udp_handle;
27
28 static gboolean hartip_desegment  = TRUE;
29
30 static int proto_hartip = -1;
31 static int hf_hartip_hdr_version = -1;
32 static int hf_hartip_hdr_message_id = -1;
33 static int hf_hartip_hdr_message_type = -1;
34 static int hf_hartip_hdr_status = -1;
35 static int hf_hartip_hdr_transaction_id = -1;
36 static int hf_hartip_hdr_msg_length = -1;
37
38 static int hf_hartip_data = -1;
39 static int hf_hartip_master_type = -1;
40 static int hf_hartip_inactivity_close_timer = -1;
41 static int hf_hartip_error_code = -1;
42
43 static int hf_hartip_pt_preambles = -1;
44 static int hf_hartip_pt_delimiter = -1;
45 static int hf_hartip_pt_short_addr = -1;
46 static int hf_hartip_pt_long_addr = -1;
47 static int hf_hartip_pt_command = -1;
48 static int hf_hartip_pt_length = -1;
49 static int hf_hartip_pt_response_code = -1;
50 static int hf_hartip_pt_device_status = -1;
51 static int hf_hartip_pt_payload = -1;
52 static int hf_hartip_pt_checksum = -1;
53
54 static gint ett_hartip = -1;
55 static gint ett_hartip_hdr = -1;
56 static gint ett_hartip_body = -1;
57
58 static expert_field ei_hartip_data_none = EI_INIT;
59 static expert_field ei_hartip_data_unexpected = EI_INIT;
60
61 /* Command 0 response */
62 static int hf_hartip_pt_rsp_expansion_code = -1;
63 static int hf_hartip_pt_rsp_expanded_device_type = -1;
64 static int hf_hartip_pt_rsp_req_min_preambles = -1;
65 static int hf_hartip_pt_rsp_hart_protocol_major_rev = -1;
66 static int hf_hartip_pt_rsp_device_rev = -1;
67 static int hf_hartip_pt_rsp_software_rev = -1;
68 static int hf_hartip_pt_rsp_hardware_rev_physical_signal = -1;
69 static int hf_hartip_pt_rsp_flage = -1;
70 static int hf_hartip_pt_rsp_device_id = -1;
71 static int hf_hartip_pt_rsp_rsp_min_preambles = -1;
72 static int hf_hartip_pt_rsp_max_device_variables = -1;
73 static int hf_hartip_pt_rsp_configuration_change_counter = -1;
74 static int hf_hartip_pt_rsp_extended_device_status = -1;
75 static int hf_hartip_pt_rsp_manufacturer_Identification_code = -1;
76 static int hf_hartip_pt_rsp_private_label = -1;
77 static int hf_hartip_pt_rsp_device_profile = -1;
78
79 /* Command 2 response */
80 static int hf_hartip_pt_rsp_pv_percent_range = -1;
81
82 /* Command 3 response */
83 static int hf_hartip_pt_rsp_pv_loop_current = -1;
84 static int hf_hartip_pt_rsp_pv_units = -1;
85 static int hf_hartip_pt_rsp_pv = -1;
86 static int hf_hartip_pt_rsp_sv_units = -1;
87 static int hf_hartip_pt_rsp_sv = -1;
88 static int hf_hartip_pt_rsp_tv_units = -1;
89 static int hf_hartip_pt_rsp_tv = -1;
90 static int hf_hartip_pt_rsp_qv_units = -1;
91 static int hf_hartip_pt_rsp_qv = -1;
92
93 /* Command 7 response*/
94 static int hf_hartip_pt_rsp_loop_current_mode = -1;
95
96 /* Command 8 response*/
97 static int hf_hartip_pt_rsp_primary_var_classify = -1;
98 static int hf_hartip_pt_rsp_secondary_var_classify = -1;
99 static int hf_hartip_pt_rsp_tertiary_var_classify = -1;
100 static int hf_hartip_pt_rsp_quaternary_var_classify = -1;
101
102 /* Command 9 response */
103 static int hf_hartip_pt_rsp_slot0_device_var = -1;
104 static int hf_hartip_pt_rsp_slot0_device_var_classify = -1;
105 static int hf_hartip_pt_rsp_slot0_units = -1;
106 static int hf_hartip_pt_rsp_slot0_device_var_value = -1;
107 static int hf_hartip_pt_rsp_slot0_device_var_status = -1;
108
109 static int hf_hartip_pt_rsp_slot1_device_var = -1;
110 static int hf_hartip_pt_rsp_slot1_device_var_classify = -1;
111 static int hf_hartip_pt_rsp_slot1_units = -1;
112 static int hf_hartip_pt_rsp_slot1_device_var_value = -1;
113 static int hf_hartip_pt_rsp_slot1_device_var_status = -1;
114
115 static int hf_hartip_pt_rsp_slot2_device_var = -1;
116 static int hf_hartip_pt_rsp_slot2_device_var_classify = -1;
117 static int hf_hartip_pt_rsp_slot2_units = -1;
118 static int hf_hartip_pt_rsp_slot2_device_var_value = -1;
119 static int hf_hartip_pt_rsp_slot2_device_var_status = -1;
120
121 static int hf_hartip_pt_rsp_slot3_device_var = -1;
122 static int hf_hartip_pt_rsp_slot3_device_var_classify = -1;
123 static int hf_hartip_pt_rsp_slot3_units = -1;
124 static int hf_hartip_pt_rsp_slot3_device_var_value = -1;
125 static int hf_hartip_pt_rsp_slot3_device_var_status = -1;
126
127 static int hf_hartip_pt_rsp_slot4_device_var = -1;
128 static int hf_hartip_pt_rsp_slot4_device_var_classify = -1;
129 static int hf_hartip_pt_rsp_slot4_units = -1;
130 static int hf_hartip_pt_rsp_slot4_device_var_value = -1;
131 static int hf_hartip_pt_rsp_slot4_device_var_status = -1;
132
133 static int hf_hartip_pt_rsp_slot5_device_var = -1;
134 static int hf_hartip_pt_rsp_slot5_device_var_classify = -1;
135 static int hf_hartip_pt_rsp_slot5_units = -1;
136 static int hf_hartip_pt_rsp_slot5_device_var_value = -1;
137 static int hf_hartip_pt_rsp_slot5_device_var_status = -1;
138
139 static int hf_hartip_pt_rsp_slot6_device_var = -1;
140 static int hf_hartip_pt_rsp_slot6_device_var_classify = -1;
141 static int hf_hartip_pt_rsp_slot6_units = -1;
142 static int hf_hartip_pt_rsp_slot6_device_var_value = -1;
143 static int hf_hartip_pt_rsp_slot6_device_var_status = -1;
144
145 static int hf_hartip_pt_rsp_slot7_device_var = -1;
146 static int hf_hartip_pt_rsp_slot7_device_var_classify = -1;
147 static int hf_hartip_pt_rsp_slot7_units = -1;
148 static int hf_hartip_pt_rsp_slot7_device_var_value = -1;
149 static int hf_hartip_pt_rsp_slot7_device_var_status = -1;
150
151 static int hf_hartip_pt_rsp_slot0_timestamp = -1;
152
153 /* Command 13 response */
154 static int hf_hartip_pt_rsp_packed_descriptor = -1;
155 static int hf_hartip_pt_rsp_day = -1;
156 static int hf_hartip_pt_rsp_month = -1;
157 static int hf_hartip_pt_rsp_year = -1;
158
159 /* Command 14 response */
160 static int hf_hartip_pt_rsp_transducer_serial_number = -1;
161 static int hf_hartip_pt_rsp_transducer_limit_min_span_units = -1;
162 static int hf_hartip_pt_rsp_upper_transducer_limit = -1;
163 static int hf_hartip_pt_rsp_lower_transducer_limit = -1;
164 static int hf_hartip_pt_rsp_minimum_span = -1;
165
166 /* Command 15 response */
167 static int hf_hartip_pt_rsp_pv_alarm_selection_code = -1;
168 static int hf_hartip_pt_rsp_pv_transfer_function_code = -1;
169 static int hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units = -1;
170 static int hf_hartip_pt_rsp_pv_upper_range_value = -1;
171 static int hf_hartip_pt_rsp_pv_lower_range_value = -1;
172 static int hf_hartip_pt_rsp_pv_damping_value = -1;
173 static int hf_hartip_pt_rsp_write_protect_code = -1;
174 static int hf_hartip_pt_rsp_reserved = -1;
175 static int hf_hartip_pt_rsp_pv_analog_channel_flags = -1;
176
177 /* Command 16 and 19 response */
178 static int hf_hartip_pt_rsp_final_assembly_number = -1;
179
180 /* response Tag */
181 static int hf_hartip_pt_rsp_tag = -1;
182
183 /* response Message */
184 static int hf_hartip_pt_rsp_message = -1;
185
186 /* Command 48 response */
187 static int hf_hartip_pt_rsp_device_sp_status = -1;
188 static int hf_hartip_pt_rsp_device_op_mode = -1;
189 static int hf_hartip_pt_rsp_standardized_status_0 = -1;
190 static int hf_hartip_pt_rsp_standardized_status_1 = -1;
191 static int hf_hartip_pt_rsp_analog_channel_saturated = -1;
192 static int hf_hartip_pt_rsp_standardized_status_2 = -1;
193 static int hf_hartip_pt_rsp_standardized_status_3 = -1;
194 static int hf_hartip_pt_rsp_analog_channel_fixed = -1;
195
196 /* Command 77 response */
197 static int hf_hartip_pt_rsp_io_card = -1;
198 static int hf_hartip_pt_rsp_channel = -1;
199 static int hf_hartip_pt_rsp_embedded_cmd_delimiter = -1;
200 static int hf_hartip_pt_rsp_poll_address = -1;
201 static int hf_hartip_pt_rsp_embedded_cmd = -1;
202
203 /* Command 31 and 178 response */
204 static int hf_hartip_pt_rsp_number_of_commands = -1;
205 static int hf_hartip_pt_rsp_command_number = -1;
206 static int hf_hartip_pt_rsp_command_byte_count = -1;
207
208 /* Command 31, 77 and 178 response */
209 static int hf_hartip_pt_rsp_data = -1;
210
211 /*Command 203 response*/
212 static int hf_hartip_pt_rsp_index_of_first_discrete_var = -1;
213 static int hf_hartip_pt_rsp_number_of_discrete_vars = -1;
214 static int hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change = -1;
215
216 static int hf_hartip_pt_rsp_slot0_discrete_var_state = -1;
217 static int hf_hartip_pt_rsp_slot0_discrete_var_status = -1;
218
219 static int hf_hartip_pt_rsp_slot1_discrete_var_state = -1;
220 static int hf_hartip_pt_rsp_slot1_discrete_var_status = -1;
221
222 static int hf_hartip_pt_rsp_slot2_discrete_var_state = -1;
223 static int hf_hartip_pt_rsp_slot2_discrete_var_status = -1;
224
225 static int hf_hartip_pt_rsp_slot3_discrete_var_state = -1;
226 static int hf_hartip_pt_rsp_slot3_discrete_var_status = -1;
227
228 static int hf_hartip_pt_rsp_slot4_discrete_var_state = -1;
229 static int hf_hartip_pt_rsp_slot4_discrete_var_status = -1;
230
231 static int hf_hartip_pt_rsp_slot5_discrete_var_state = -1;
232 static int hf_hartip_pt_rsp_slot5_discrete_var_status = -1;
233
234 #define HARTIP_HEADER_LENGTH     8
235 #define HARTIP_PORT           5094
236
237 /* HARTIP header */
238 typedef struct _hartip_hdr {
239   guint8   version;
240   guint8   message_type;
241   guint8   message_id;
242   guint8   status;
243   guint16  transaction_id;
244   guint16  length;
245 } hartip_hdr;
246
247 /* Message IDs */
248 #define SESSION_INITIATE_ID       0
249 #define SESSION_CLOSE_ID          1
250 #define KEEP_ALIVE_ID             2
251 #define PASS_THROUGH_ID           3
252
253 /* Message types */
254 #define REQUEST_MSG_TYPE       0
255 #define RESPONSE_MSG_TYPE      1
256 #define PUBLISH_MSG_TYPE       2
257 #define ERROR_MSG_TYPE         3
258 #define NAK_MSG_TYPE           15
259
260 static const value_string hartip_message_id_values[] = {
261   { SESSION_INITIATE_ID,     "Session Initiate" },
262   { SESSION_CLOSE_ID,        "Session Close" },
263   { KEEP_ALIVE_ID,           "Keep Alive" },
264   { PASS_THROUGH_ID,         "Pass Through" },
265   { 0, NULL }
266 };
267
268 static const value_string hartip_message_type_values[] = {
269   { REQUEST_MSG_TYPE,        "Request" },
270   { RESPONSE_MSG_TYPE,       "Response" },
271   { PUBLISH_MSG_TYPE,        "Publish" },
272   { ERROR_MSG_TYPE,          "Error" },
273   { NAK_MSG_TYPE,            "Error" },
274   { 0, NULL }
275 };
276
277 /* Host types */
278 #define SECONDARY_MASTER_TYPE    0
279 #define PRIMARY_MASTER_TYPE      1
280
281 static const value_string hartip_master_type_values[] = {
282   { SECONDARY_MASTER_TYPE,      "Secondary Host" },
283   { PRIMARY_MASTER_TYPE,        "Primary Host" },
284   { 0, NULL }
285 };
286
287 /* Error Codes */
288 #define SESSION_CLOSED_ERROR                0
289 #define PRIMARY_SESSION_UNAVAILABLE_ERROR   1
290 #define SERVICE_UNAVAILABLE_ERROR           2
291
292 static const value_string hartip_error_code_values[] = {
293   { SESSION_CLOSED_ERROR,              "Session closed" },
294   { PRIMARY_SESSION_UNAVAILABLE_ERROR, "Primary session unavailable" },
295   { SERVICE_UNAVAILABLE_ERROR,         "Service unavailable" },
296   { 0, NULL }
297 };
298
299 /* Handle for statistics tap. */
300 static int hartip_tap = -1;
301
302 /* Structure used for passing data for statistics processing. */
303 typedef struct _hartip_tap_info {
304   gint8  message_type;
305   gint8  message_id;
306 } hartip_tap_info;
307
308 /* Names of items in statistics tree. */
309 static const gchar* st_str_packets   = "Total HART_IP Packets";
310 static const gchar* st_str_requests  = "Request Packets";
311 static const gchar* st_str_responses = "Response Packets";
312 static const gchar* st_str_publish   = "Publish Packets";
313 static const gchar* st_str_errors    = "Error Packets";
314
315 /* Handles of items in statistics tree. */
316 static int st_node_packets = -1;
317 static int st_node_requests = -1;
318 static int st_node_responses = -1;
319 static int st_node_publish = -1;
320 static int st_node_errors = -1;
321
322 static void
323 hartip_stats_tree_init(stats_tree* st)
324 {
325   st_node_packets   = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, TRUE);
326   st_node_requests  = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
327   st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, STAT_DT_INT, TRUE);
328   st_node_publish   = stats_tree_create_node(st, st_str_publish, st_node_packets, STAT_DT_INT, TRUE);
329   st_node_errors    = stats_tree_create_node(st, st_str_errors, st_node_packets, STAT_DT_INT, TRUE);
330 }
331
332 static tap_packet_status
333 hartip_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_,
334                          epan_dissect_t* edt _U_, const void* p)
335 {
336   const hartip_tap_info *tapinfo = (const hartip_tap_info *)p;
337   const gchar           *message_type_node_str, *message_id_node_str;
338   int                    message_type_node;
339
340   switch (tapinfo->message_type) {
341   case REQUEST_MSG_TYPE:
342     message_type_node_str = st_str_requests;
343     message_type_node     = st_node_requests;
344     break;
345   case RESPONSE_MSG_TYPE:
346     message_type_node_str = st_str_responses;
347     message_type_node     = st_node_responses;
348     break;
349   case PUBLISH_MSG_TYPE:
350     message_type_node_str = st_str_publish;
351     message_type_node     = st_node_publish;
352     break;
353   case ERROR_MSG_TYPE:
354   case NAK_MSG_TYPE:
355     message_type_node_str = st_str_errors;
356     message_type_node     = st_node_errors;
357     break;
358   default:
359     return TAP_PACKET_DONT_REDRAW;  /* Don't want to track invalid messages for now. */
360   }
361
362   message_id_node_str = val_to_str(tapinfo->message_id,
363                                    hartip_message_id_values,
364                                    "Unknown message %d");
365
366   tick_stat_node(st, st_str_packets, 0, FALSE);
367   tick_stat_node(st, message_type_node_str, st_node_packets, FALSE);
368   tick_stat_node(st, message_id_node_str, message_type_node, FALSE);
369
370   return TAP_PACKET_REDRAW;
371 }
372
373 static gint
374 dissect_empty_body(proto_tree *tree, packet_info* pinfo, tvbuff_t *tvb,
375                    gint offset, gint bodylen)
376 {
377   proto_item  *ti;
378
379   ti = proto_tree_add_item(tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
380   if (bodylen == 0) {
381     expert_add_info(pinfo, ti, &ei_hartip_data_none);
382   } else {
383     expert_add_info(pinfo, ti, &ei_hartip_data_unexpected);
384   }
385   return bodylen;
386 }
387
388 static gint
389 dissect_session_init(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
390                      gint bodylen)
391 {
392   if (bodylen == 5) {
393     proto_tree_add_item(body_tree, hf_hartip_master_type, tvb, offset, 1, ENC_BIG_ENDIAN);
394     offset += 1;
395
396     proto_tree_add_item(body_tree, hf_hartip_inactivity_close_timer, tvb, offset, 4, ENC_BIG_ENDIAN);
397   } else {
398     proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
399   }
400
401   return bodylen;
402 }
403
404 static gint
405 dissect_error(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
406 {
407   if (bodylen == 1) {
408     proto_tree_add_item(body_tree, hf_hartip_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
409   } else {
410     proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
411   }
412
413   return bodylen;
414 }
415
416 static gint
417 dissect_session_close(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
418                       gint offset, gint bodylen)
419 {
420   return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
421 }
422
423 static gint
424 dissect_keep_alive(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb,
425                    gint offset, gint bodylen)
426 {
427   return dissect_empty_body(body_tree, pinfo, tvb, offset, bodylen);
428 }
429
430 static gint
431 dissect_byte(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
432 {
433   proto_tree_add_item(tree, hf, tvb, offset, 1, ENC_BIG_ENDIAN);
434   return 1;
435 }
436
437 static gint
438 dissect_short(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
439 {
440   proto_tree_add_item(tree, hf, tvb, offset, 2, ENC_BIG_ENDIAN);
441   return 2;
442 }
443
444 static gint
445 dissect_float(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset)
446 {
447   proto_tree_add_item(tree, hf, tvb, offset, 4, ENC_BIG_ENDIAN);
448   return 4;
449 }
450
451 static gint
452 dissect_packAscii(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset, int len)
453 {
454   gushort     usIdx;
455   gushort     usGroupCnt;
456   gushort     usMaxGroups;      /* Number of 4 byte groups to pack. */
457   gushort     usMask;
458   gint        iIndex;
459   gint        i   = 0;
460   gushort     buf[4];
461   guint8     *tmp;
462   char       *str = NULL;
463
464   tmp = (guint8 *)wmem_alloc0(wmem_packet_scope(), len);
465   tvb_memcpy(tvb, tmp, offset, len);
466
467   /* Maximum possible unpacked length = (len / 3) * 4 */
468   str = (char *)wmem_alloc(wmem_packet_scope(), ((len / 3) * 4)+1);
469
470   iIndex = 0;
471   usMaxGroups = (gushort)(len / 3);
472   for (usGroupCnt = 0; usGroupCnt < usMaxGroups; usGroupCnt++) {
473     /*
474      * First unpack 3 bytes into a group of 4 bytes, clearing bits 6 & 7.
475      */
476     buf[0] = (gushort)(tmp[iIndex] >> 2);
477     buf[1] = (gushort)(((tmp[iIndex] << 4) & 0x30) | (tmp[iIndex + 1] >> 4));
478     buf[2] = (gushort)(((tmp[iIndex + 1] << 2) & 0x3C) | (tmp[iIndex + 2] >> 6));
479     buf[3] = (gushort)(tmp[iIndex + 2] & 0x3F);
480     iIndex += 3;
481
482     /*
483      * Now transfer to unpacked area, setting bit 6 to complement of bit 5.
484      */
485     for (usIdx = 0; usIdx < 4; usIdx++) {
486       usMask = (gushort)(((buf[usIdx] & 0x20) << 1) ^ 0x40);
487       DISSECTOR_ASSERT(i < 256);
488       str[i++] = (gchar)(buf[usIdx] | usMask);
489     }
490   }
491   str[i] = '\0';
492
493   proto_tree_add_string(tree, hf, tvb, offset, len, str);
494
495   return len;
496 }
497
498 static gint
499 dissect_timestamp(proto_tree *tree, int hf, const char *name, int len,
500                   tvbuff_t *tvb, gint offset)
501 {
502   proto_item *ti;
503   guint32     t;
504   guint32     hrs  = 0;
505   guint32     mins = 0;
506   guint32     secs = 0;
507   guint32     ms   = 0;
508
509   ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA);
510   t  = tvb_get_ntohl(tvb, offset);
511
512   if (t > 0 ) {
513     t /= 32;
514     ms = t % 1000;
515     t /= 1000;
516     secs = t % 60;
517     t /= 60;
518     mins = t % 60;
519     hrs = (guint)(t / 60);
520   }
521
522   proto_item_set_text(ti, "%s: %02d:%02d:%02d.%03d", name, hrs, mins, secs, ms);
523   return len;
524 }
525
526 static gint
527 dissect_cmd0(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
528 {
529   if (bodylen >= 12) {
530     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_expansion_code,                   tvb, offset);
531     offset += dissect_short(body_tree, hf_hartip_pt_rsp_expanded_device_type,             tvb, offset);
532     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_req_min_preambles,                tvb, offset);
533     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_hart_protocol_major_rev,          tvb, offset);
534     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_device_rev,                       tvb, offset);
535     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_software_rev,                     tvb, offset);
536     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_hardware_rev_physical_signal,     tvb, offset);
537     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_flage,                            tvb, offset);
538     proto_tree_add_item(body_tree,     hf_hartip_pt_rsp_device_id,                        tvb, offset, 3, ENC_NA);
539     offset += 3;
540
541     if (bodylen >= 16) {
542       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_rsp_min_preambles,                tvb, offset);
543       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_max_device_variables,             tvb, offset);
544       offset += dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter,     tvb, offset);
545       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_extended_device_status,           tvb, offset);
546     }
547
548     if (bodylen >= 18) {
549       offset += dissect_short(body_tree, hf_hartip_pt_rsp_manufacturer_Identification_code, tvb, offset);
550     }
551
552     if (bodylen >= 22) {
553       offset += dissect_short(body_tree, hf_hartip_pt_rsp_private_label,                    tvb, offset);
554       /*offset += */dissect_byte(body_tree,  hf_hartip_pt_rsp_device_profile,                   tvb, offset);
555     }
556
557     return bodylen;
558   }
559
560   return 0;
561 }
562
563 static gint
564 dissect_cmd1(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
565 {
566   if (bodylen >= 5) {
567     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_pv_units, tvb, offset);
568     /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv,       tvb, offset);
569     return bodylen;
570   }
571
572   return 0;
573 }
574
575 static gint
576 dissect_cmd2(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
577 {
578   if (bodylen >= 8) {
579     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current,  tvb, offset);
580     /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_pv_percent_range, tvb, offset);
581     return bodylen;
582   }
583
584   return 0;
585 }
586
587 static gint
588 dissect_cmd3(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
589 {
590   if (bodylen >= 24) {
591     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
592     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_pv_units,        tvb, offset);
593     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv,              tvb, offset);
594     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_sv_units,        tvb, offset);
595     offset += dissect_float(body_tree, hf_hartip_pt_rsp_sv,              tvb, offset);
596     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_tv_units,        tvb, offset);
597     offset += dissect_float(body_tree, hf_hartip_pt_rsp_tv,              tvb, offset);
598     offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_qv_units,        tvb, offset);
599     /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_qv,              tvb, offset);
600
601     return bodylen;
602   }
603
604   return 0;
605 }
606
607 static gint
608 dissect_cmd7(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
609 {
610   if (bodylen >= 2) {
611     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address,     tvb, offset);
612     dissect_byte(body_tree, hf_hartip_pt_rsp_loop_current_mode,          tvb, offset);
613
614     return bodylen;
615   }
616    return 0;
617 }
618
619 static gint
620 dissect_cmd8(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
621 {
622   if (bodylen >= 4) {
623     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_primary_var_classify,     tvb, offset);
624     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_secondary_var_classify,   tvb, offset);
625     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_tertiary_var_classify,    tvb, offset);
626     dissect_byte(body_tree, hf_hartip_pt_rsp_quaternary_var_classify,            tvb, offset);
627
628     return bodylen;
629   }
630    return 0;
631 }
632
633 static gint
634 dissect_cmd9(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
635 {
636   if (bodylen >= 13) {
637     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_extended_device_status,    tvb, offset);
638     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_device_var,          tvb, offset);
639     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_device_var_classify, tvb, offset);
640     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_units,               tvb, offset);
641     offset += dissect_float(body_tree,   hf_hartip_pt_rsp_slot0_device_var_value,    tvb, offset);
642     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_device_var_status,   tvb, offset);
643
644     if (bodylen >= 21) {
645       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot1_device_var,          tvb, offset);
646       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot1_device_var_classify, tvb, offset);
647       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot1_units,               tvb, offset);
648       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot1_device_var_value,    tvb, offset);
649       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot1_device_var_status,   tvb, offset);
650     }
651
652     if (bodylen >= 29) {
653       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot2_device_var,          tvb, offset);
654       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot2_device_var_classify, tvb, offset);
655       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot2_units,               tvb, offset);
656       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot2_device_var_value,    tvb, offset);
657       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot2_device_var_status,   tvb, offset);
658     }
659
660     if (bodylen >= 37) {
661       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot3_device_var,          tvb, offset);
662       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot3_device_var_classify, tvb, offset);
663       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot3_units,               tvb, offset);
664       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot3_device_var_value,    tvb, offset);
665       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot3_device_var_status,   tvb, offset);
666     }
667
668     if (bodylen >= 45) {
669       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot4_device_var,          tvb, offset);
670       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot4_device_var_classify, tvb, offset);
671       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot4_units,               tvb, offset);
672       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot4_device_var_value,    tvb, offset);
673       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot4_device_var_status,   tvb, offset);
674     }
675
676     if (bodylen >= 53) {
677       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot5_device_var,          tvb, offset);
678       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot5_device_var_classify, tvb, offset);
679       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot5_units,               tvb, offset);
680       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot5_device_var_value,    tvb, offset);
681       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot5_device_var_status,   tvb, offset);
682     }
683
684     if (bodylen >= 61) {
685       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot6_device_var,          tvb, offset);
686       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot6_device_var_classify, tvb, offset);
687       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot6_units,               tvb, offset);
688       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot6_device_var_value,    tvb, offset);
689       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot6_device_var_status,   tvb, offset);
690     }
691
692     if (bodylen >= 69) {
693       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot7_device_var,          tvb, offset);
694       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot7_device_var_classify, tvb, offset);
695       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot7_units,               tvb, offset);
696       offset += dissect_float(body_tree, hf_hartip_pt_rsp_slot7_device_var_value,    tvb, offset);
697       offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_slot7_device_var_status,   tvb, offset);
698     }
699
700     dissect_timestamp(body_tree, hf_hartip_pt_rsp_slot0_timestamp, "Slot0 Data TimeStamp", 4, tvb, offset);
701
702     return bodylen;
703   }
704
705   return 0;
706 }
707
708 static gint
709 dissect_cmd13(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
710 {
711   if (bodylen >= 21) {
712     offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 6);
713     offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_packed_descriptor, tvb, offset, 12);
714     offset += dissect_byte(body_tree,      hf_hartip_pt_rsp_day,                                 tvb, offset);
715     offset += dissect_byte(body_tree,      hf_hartip_pt_rsp_month,                               tvb, offset);
716     /*offset += */dissect_byte(body_tree,      hf_hartip_pt_rsp_year,                                tvb, offset);
717
718     return bodylen;
719   }
720
721   return 0;
722 }
723
724 static gint
725 dissect_cmd14(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
726 {
727   if (bodylen >= 16) {
728     proto_tree_add_item(body_tree, hf_hartip_pt_rsp_transducer_serial_number, tvb, offset, 3, ENC_NA);
729     offset += 3;
730     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_transducer_limit_min_span_units, tvb, offset);
731     offset += dissect_float(body_tree, hf_hartip_pt_rsp_upper_transducer_limit,         tvb, offset);
732     offset += dissect_float(body_tree, hf_hartip_pt_rsp_lower_transducer_limit,         tvb, offset);
733     dissect_float(body_tree, hf_hartip_pt_rsp_minimum_span,                             tvb, offset);
734
735     return bodylen;
736   }
737
738   return 0;
739 }
740
741 static gint
742 dissect_cmd15(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
743 {
744   if (bodylen >= 18) {
745     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_alarm_selection_code,               tvb, offset);
746     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_transfer_function_code,             tvb, offset);
747     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units, tvb, offset);
748     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_upper_range_value,                 tvb, offset);
749     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_lower_range_value,                 tvb, offset);
750     offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_damping_value,                     tvb, offset);
751     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_write_protect_code,                    tvb, offset);
752     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_reserved,                              tvb, offset);
753     dissect_byte(body_tree, hf_hartip_pt_rsp_pv_analog_channel_flags,                         tvb, offset);
754
755     return bodylen;
756   }
757
758   return 0;
759 }
760
761 static gint
762 dissect_cmd16(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
763 {
764   if (bodylen >= 3) {
765     proto_tree_add_item(body_tree, hf_hartip_pt_rsp_final_assembly_number, tvb, offset, 3, ENC_NA);
766
767     return bodylen;
768   }
769
770   return 0;
771 }
772
773 static gint
774 dissect_cmd33(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
775 {
776   if (bodylen >= 6) {
777     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_device_var,          tvb, offset);
778     offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot0_units,               tvb, offset);
779     offset += dissect_float(body_tree,   hf_hartip_pt_rsp_slot0_device_var_value,    tvb, offset);
780
781     if (bodylen >= 12) {
782       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot1_device_var,        tvb, offset);
783       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot1_units,             tvb, offset);
784       offset += dissect_float(body_tree,   hf_hartip_pt_rsp_slot1_device_var_value,  tvb, offset);
785     }
786
787     if (bodylen >= 18) {
788       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot2_device_var,        tvb, offset);
789       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot2_units,             tvb, offset);
790       offset += dissect_float(body_tree,   hf_hartip_pt_rsp_slot2_device_var_value,  tvb, offset);
791     }
792
793     if (bodylen >= 24) {
794       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot3_device_var,        tvb, offset);
795       offset += dissect_byte(body_tree,    hf_hartip_pt_rsp_slot3_units,             tvb, offset);
796       dissect_float(body_tree,   hf_hartip_pt_rsp_slot3_device_var_value,            tvb, offset);
797     }
798
799     return bodylen;
800   }
801
802   return 0;
803 }
804
805 static gint
806 dissect_cmd38(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
807 {
808   if (bodylen >= 2) {
809     dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter, tvb, offset);
810
811    return bodylen;
812   }
813
814   return 0;
815 }
816
817 static gint
818 dissect_cmd48(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
819 {
820   if (bodylen >= 6) {
821     proto_tree_add_item(body_tree,      hf_hartip_pt_rsp_device_sp_status,         tvb, offset, 6, ENC_NA);
822     offset += 6;
823
824     if (bodylen >= 9) {
825       offset += dissect_byte(body_tree,   hf_hartip_pt_rsp_extended_device_status, tvb, offset);
826       offset += dissect_byte(body_tree,   hf_hartip_pt_rsp_device_op_mode,         tvb, offset);
827       offset += dissect_byte(body_tree,   hf_hartip_pt_rsp_standardized_status_0,  tvb, offset);
828     }
829
830     if (bodylen >= 13) {
831       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_1,    tvb, offset);
832       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_saturated, tvb, offset);
833       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_2,    tvb, offset);
834       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_standardized_status_3,    tvb, offset);
835     }
836
837     if (bodylen >= 14) {
838         offset += dissect_byte(body_tree, hf_hartip_pt_rsp_analog_channel_fixed,   tvb, offset);
839     }
840
841     if (bodylen >= 24) {
842       proto_tree_add_item(body_tree,    hf_hartip_pt_rsp_device_sp_status,         tvb, offset, 11, ENC_NA);
843       /*offset += 11;*/
844     }
845     return bodylen;
846   }
847
848   return 0;
849 }
850
851 static gint
852 dissect_cmd77(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
853 {
854   guint8  byte_count;
855   gint    length = bodylen;
856
857   if (length >= 6) {
858      offset += dissect_byte(body_tree, hf_hartip_pt_rsp_io_card,                tvb, offset);
859      offset += dissect_byte(body_tree, hf_hartip_pt_rsp_channel,                tvb, offset);
860      offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd_delimiter, tvb, offset);
861      offset += dissect_byte(body_tree, hf_hartip_pt_rsp_poll_address,           tvb, offset);
862      offset += dissect_byte(body_tree, hf_hartip_pt_rsp_embedded_cmd,           tvb, offset);
863
864      byte_count = tvb_get_guint8(tvb, offset);
865      proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
866      offset += 1;
867      length -= 6;
868
869      if ((byte_count >= 2) && (length >= 2) && (byte_count <= length)) {
870        offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
871        offset += dissect_byte(body_tree, hf_hartip_pt_device_status, tvb, offset);
872        length -= 2;
873        byte_count -= 2;
874
875        if ((byte_count > 0) && (length > 0) && (byte_count <= length)) {
876          proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
877                              byte_count, ENC_NA);
878        }
879      }
880
881     return bodylen;
882   }
883
884   return 0;
885 }
886
887 static gint
888 dissect_cmd178(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
889 {
890    guint16 cmd;
891    guint8  number_of_cmds;
892    guint8  cmd_byte_count;
893    gint    length = bodylen;
894    gint8   i;
895    gint    result;
896
897    if (length >= 5) {
898      number_of_cmds = tvb_get_guint8(tvb, offset);
899      proto_tree_add_uint(body_tree, hf_hartip_pt_rsp_number_of_commands, tvb, offset, 1, number_of_cmds);
900      offset += 1;
901      length -= 1;
902
903      for (i = 0; i < number_of_cmds; i++)
904      {
905        if (length >= 4)
906        {
907          cmd = tvb_get_ntohs(tvb, offset);
908          proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
909          offset += 2;
910          length -= 2;
911
912          cmd_byte_count = tvb_get_guint8(tvb, offset);
913          proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
914          offset += 1;
915          length -= 1;
916
917          offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
918          length -= 1;
919          cmd_byte_count -= 1;
920
921          if ((cmd_byte_count > 0) && (length > 0) && (cmd_byte_count <= length))
922          {
923            switch(cmd)
924            {
925              case 3:
926                result = dissect_cmd3(body_tree, tvb, offset, cmd_byte_count);
927                break;
928              case 9:
929                result = dissect_cmd9(body_tree, tvb, offset, cmd_byte_count);
930                break;
931              case 48:
932                result = dissect_cmd48(body_tree, tvb, offset, cmd_byte_count);
933                break;
934              default:
935                result = 0;
936                break;
937            }
938
939            if (result == 0 ) {
940              proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
941                                  cmd_byte_count, ENC_NA);
942            }
943
944            offset += cmd_byte_count;
945            length -= cmd_byte_count;
946          }
947        } else {
948          return bodylen;
949        }
950      }
951
952      return bodylen;
953    }
954
955    return 0;
956 }
957
958 static gint
959 dissect_cmd203(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
960 {
961   if (bodylen >= 8) {
962     offset += dissect_short(body_tree, hf_hartip_pt_rsp_index_of_first_discrete_var, tvb, offset);
963     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_number_of_discrete_vars,      tvb, offset);
964     offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status,       tvb, offset);
965     dissect_timestamp(body_tree, hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
966                       "TimeStamp for Most Recent Discrete Change", 4,                tvb, offset);
967     offset += 4;
968
969     if (bodylen >= 11)
970     {
971        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_state, tvb, offset);
972        offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_status, tvb, offset);
973     }
974
975     if (bodylen >= 14)
976     {
977        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_state, tvb, offset);
978        offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_status, tvb, offset);
979     }
980
981     if (bodylen >= 17)
982     {
983        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_state, tvb, offset);
984        offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_status, tvb, offset);
985     }
986
987     if (bodylen >= 20)
988     {
989        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_state, tvb, offset);
990        offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_status, tvb, offset);
991     }
992
993     if (bodylen >= 23)
994     {
995        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_state, tvb, offset);
996        offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_status, tvb, offset);
997     }
998
999     if (bodylen >= 26)
1000     {
1001        offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_state, tvb, offset);
1002        dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_status,           tvb, offset);
1003     }
1004
1005     return bodylen;
1006   }
1007
1008   return 0;
1009 }
1010
1011 static gint
1012 dissect_cmd31(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen)
1013 {
1014   gint    length = bodylen;
1015   gint    result = 0;
1016   guint16 cmd;
1017
1018   if (length >= 2) {
1019     cmd = tvb_get_ntohs(tvb, offset);
1020     proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
1021     offset += 2;
1022     length -= 2;
1023
1024     if (length > 0) {
1025       switch(cmd)
1026       {
1027         case 64386:
1028           result = dissect_cmd203(body_tree, tvb, offset, length);
1029           break;
1030       }
1031
1032       if (result == 0) {
1033         proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
1034                             length, ENC_NA);
1035       }
1036     }
1037
1038     return bodylen;
1039   }
1040
1041   return 0;
1042 }
1043
1044 static gint
1045 dissect_parse_hart_cmds(proto_tree *body_tree, tvbuff_t *tvb, guint8 cmd,
1046                         gint offset, gint bodylen)
1047 {
1048   switch(cmd)
1049   {
1050   case 0:
1051   case 11:
1052   case 21:
1053     return dissect_cmd0(body_tree, tvb, offset, bodylen);
1054   case 1:
1055     return dissect_cmd1(body_tree, tvb, offset, bodylen);
1056   case 2:
1057     return dissect_cmd2(body_tree, tvb, offset, bodylen);
1058   case 3:
1059     return dissect_cmd3(body_tree, tvb, offset, bodylen);
1060   case 6:
1061   case 7:
1062     return dissect_cmd7(body_tree, tvb, offset, bodylen);
1063   case 8:
1064     return dissect_cmd8(body_tree, tvb, offset, bodylen);
1065   case 9:
1066     return dissect_cmd9(body_tree, tvb, offset, bodylen);
1067   case 12:
1068   case 17:
1069     if (bodylen >= 24)
1070       return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, tvb, offset, 24);
1071     break;
1072   case 13:
1073   case 18:
1074     return dissect_cmd13(body_tree, tvb, offset, bodylen);
1075   case 14:
1076     return dissect_cmd14(body_tree, tvb, offset, bodylen);
1077   case 15:
1078     return dissect_cmd15(body_tree, tvb, offset, bodylen);
1079   case 16:
1080   case 19:
1081     return dissect_cmd16(body_tree, tvb, offset, bodylen);
1082   case 20:
1083   case 22:
1084     if (bodylen >= 32) {
1085       proto_tree_add_item(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 32,
1086                           ENC_ASCII|ENC_NA);
1087       return 32;
1088     }
1089     break;
1090   case 31:
1091     return dissect_cmd31(body_tree, tvb, offset, bodylen);
1092   case 33:
1093     return dissect_cmd33(body_tree, tvb, offset, bodylen);
1094   case 38:
1095     return dissect_cmd38(body_tree, tvb, offset, bodylen);
1096   case 48:
1097     return dissect_cmd48(body_tree, tvb, offset, bodylen);
1098   case 77:
1099     return dissect_cmd77(body_tree, tvb, offset, bodylen);
1100   case 178:
1101     return dissect_cmd178(body_tree, tvb, offset, bodylen);
1102   case 203:
1103     return dissect_cmd203(body_tree, tvb, offset, bodylen);
1104   }
1105
1106   return 0;
1107 }
1108
1109 static gint
1110 dissect_pass_through(proto_tree *body_tree, tvbuff_t *tvb, gint offset,
1111                      gint bodylen)
1112 {
1113   proto_item *ti;
1114   guint8      delimiter;
1115   const char *frame_type_str;
1116   guint8      cmd           = 0;
1117   gint        length        = bodylen;
1118   gint        is_short      = 0;
1119   gint        is_rsp        = 0;
1120   gint        num_preambles = 0;
1121   gint        result;
1122   guint8      short_addr;
1123
1124   /* find number of preambles */
1125   while (length > num_preambles) {
1126     delimiter = tvb_get_guint8(tvb, offset + num_preambles);
1127     if (delimiter != 0xFF)
1128       break;
1129
1130     num_preambles += 1;
1131   }
1132
1133   if (num_preambles > 0) {
1134     proto_tree_add_item(body_tree, hf_hartip_pt_preambles, tvb, offset,
1135                         num_preambles, ENC_NA);
1136     offset += num_preambles;
1137     length -= num_preambles;
1138   }
1139
1140   if (length > 0) {
1141     delimiter = tvb_get_guint8(tvb, offset);
1142     ti = proto_tree_add_uint(body_tree, hf_hartip_pt_delimiter, tvb, offset, 1,
1143                              delimiter);
1144     offset += 1;
1145     length -= 1;
1146
1147     if ((delimiter & 0x7) == 2) {
1148       frame_type_str = "STX";
1149     } else if ((delimiter & 0x7) == 6) {
1150       frame_type_str = "ACK";
1151       is_rsp = 1;
1152     } else if ((delimiter & 0x7) == 1) {
1153       frame_type_str = "PUB";
1154       is_rsp = 1;
1155     } else {
1156       frame_type_str = "UNK";
1157     }
1158
1159     if ((delimiter & 0x80) == 0) {
1160       is_short = 1;
1161       proto_item_set_text(ti, "Short Address, Frame Type: %s", frame_type_str);
1162     } else {
1163       proto_item_set_text(ti, "Frame Type: %s", frame_type_str);
1164     }
1165   }
1166
1167   if (is_short == 1) {
1168     if (length > 0) {
1169       short_addr = tvb_get_guint8(tvb, offset);
1170       short_addr = short_addr & 0x3F;
1171       proto_tree_add_uint(body_tree, hf_hartip_pt_short_addr, tvb, offset, 1,
1172                                short_addr);
1173       offset += 1;
1174       length -= 1;
1175     }
1176   } else {
1177     if (length > 4) {
1178       proto_tree_add_item(body_tree, hf_hartip_pt_long_addr, tvb, offset, 5, ENC_NA);
1179       offset += 5;
1180       length -= 5;
1181     } else if (length > 0) {
1182       proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, length, ENC_NA);
1183       length = 0;
1184     }
1185   }
1186
1187   if (length > 0) {
1188     cmd = tvb_get_guint8(tvb, offset);
1189     proto_tree_add_item(body_tree, hf_hartip_pt_command, tvb, offset, 1, ENC_BIG_ENDIAN);
1190     offset += 1;
1191     length -= 1;
1192   }
1193   if (length > 0) {
1194     proto_tree_add_item(body_tree, hf_hartip_pt_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1195     offset += 1;
1196     length -= 1;
1197   }
1198
1199   if (is_rsp == 1) {
1200     if (length > 0) {
1201       proto_tree_add_item(body_tree, hf_hartip_pt_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1202       offset += 1;
1203       length -= 1;
1204     }
1205     if (length > 0) {
1206       proto_tree_add_item(body_tree, hf_hartip_pt_device_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1207       offset += 1;
1208       length -= 1;
1209     }
1210   }
1211
1212   if (length > 1) {
1213     result = dissect_parse_hart_cmds(body_tree, tvb, cmd, offset, (length - 1));
1214     if (result == 0 ) {
1215       proto_tree_add_item(body_tree, hf_hartip_pt_payload, tvb, offset,
1216                           (length - 1), ENC_NA);
1217     }
1218     offset += (length - 1);
1219     length = 1;
1220   }
1221   if (length > 0) {
1222     proto_tree_add_checksum(body_tree, tvb, offset, hf_hartip_pt_checksum, -1, NULL, NULL, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1223   }
1224
1225   return bodylen;
1226 }
1227
1228 static void
1229 hartip_set_conversation(packet_info *pinfo)
1230 {
1231   conversation_t *conversation = NULL;
1232
1233   if (!pinfo->fd->visited && (pinfo->ptype == PT_UDP)) {
1234     /*
1235      * This function is called for a session initiate send over UDP.
1236      * The session initiate is sent to the server on port HARTIP_PORT.
1237      * The server then responds from a different port.  All subsequent
1238      * communication for the session between the client and server
1239      * uses the new server port and the original client port.
1240      *
1241      * A new conversation is created here and this dissector is set to
1242      * be used for it.  This allows the packets to be dissected properly
1243      * for this protocol.
1244      */
1245     conversation = find_conversation(pinfo->num,
1246                                      &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1247                                      pinfo->srcport, 0, NO_PORT_B);
1248     if( (conversation == NULL) ||
1249         (conversation_get_dissector(conversation, pinfo->num) != hartip_udp_handle) ) {
1250       conversation = conversation_new(pinfo->num,
1251                                       &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1252                                       pinfo->srcport, 0, NO_PORT2);
1253       conversation_set_dissector(conversation, hartip_udp_handle);
1254     }
1255   }
1256 }
1257
1258 static int
1259 dissect_hartip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1260                       gint offset)
1261 {
1262   proto_tree      *hartip_tree, *hdr_tree, *body_tree;
1263   proto_item      *hart_item;
1264   gint             bodylen;
1265   guint8           message_type, message_id;
1266   guint16          transaction_id, length;
1267   const char      *msg_id_str, *msg_type_str;
1268   hartip_tap_info *tapinfo;
1269
1270   col_set_str(pinfo->cinfo, COL_PROTOCOL, "HART_IP");
1271   col_clear(pinfo->cinfo, COL_INFO);
1272
1273   length  = tvb_get_ntohs(tvb, offset+6);
1274
1275   hart_item = proto_tree_add_item(tree, proto_hartip, tvb, 0, length, ENC_NA);
1276   hartip_tree = proto_item_add_subtree(hart_item, ett_hartip);
1277
1278   hdr_tree = proto_tree_add_subtree(hartip_tree, tvb, offset, HARTIP_HEADER_LENGTH,
1279                       ett_hartip_hdr, NULL, "HART_IP Header");
1280
1281   proto_tree_add_item(hdr_tree, hf_hartip_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1282   offset += 1;
1283
1284   message_type = tvb_get_guint8(tvb, offset);
1285   msg_type_str = val_to_str(message_type, hartip_message_type_values, "Unknown message type %d");
1286   proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1287   offset += 1;
1288
1289   message_id = tvb_get_guint8(tvb, offset);
1290   msg_id_str = val_to_str(message_id, hartip_message_id_values, "Unknown message %d");
1291   proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1292   offset += 1;
1293
1294   /* Setup statistics for tap. */
1295   tapinfo = wmem_new(wmem_packet_scope(), hartip_tap_info);
1296   tapinfo->message_type = message_type;
1297   tapinfo->message_id   = message_id;
1298   tap_queue_packet(hartip_tap, pinfo, tapinfo);
1299
1300   if (message_id == SESSION_INITIATE_ID) {
1301     hartip_set_conversation(pinfo);
1302   }
1303
1304   proto_tree_add_item(hdr_tree, hf_hartip_hdr_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1305   offset += 1;
1306
1307   transaction_id = tvb_get_ntohs(tvb, offset);
1308   proto_tree_add_item(hdr_tree, hf_hartip_hdr_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1309   offset += 2;
1310
1311   proto_item_append_text(hart_item, ", %s %s, Sequence Number %d", msg_id_str,
1312                          msg_type_str, transaction_id);
1313
1314   col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ",
1315                       "%s %s, Sequence Number %d",
1316                       msg_id_str, msg_type_str, transaction_id);
1317   col_set_fence(pinfo->cinfo, COL_INFO);
1318
1319   proto_tree_add_item(hdr_tree, hf_hartip_hdr_msg_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1320   offset += 2;
1321
1322   if (length < HARTIP_HEADER_LENGTH)
1323     return tvb_reported_length(tvb);
1324   bodylen = length - HARTIP_HEADER_LENGTH;
1325
1326   /* add body elements. */
1327   body_tree = proto_tree_add_subtree_format(hartip_tree, tvb, offset, bodylen,
1328                            ett_hartip_body, NULL,
1329                            "HART_IP Body, %s, %s", msg_id_str, msg_type_str);
1330
1331   if ((message_type == ERROR_MSG_TYPE) ||
1332       (message_type == NAK_MSG_TYPE)) {
1333     offset += dissect_error(body_tree, tvb, offset, bodylen);
1334   } else {
1335     /*  Dissect the various HARTIP messages. */
1336     switch(message_id) {
1337     case SESSION_INITIATE_ID:
1338       offset += dissect_session_init(body_tree, tvb, offset, bodylen);
1339       break;
1340     case SESSION_CLOSE_ID:
1341       offset += dissect_session_close(body_tree, pinfo, tvb, offset, bodylen);
1342       break;
1343     case KEEP_ALIVE_ID:
1344       offset += dissect_keep_alive(body_tree, pinfo, tvb, offset, bodylen);
1345       break;
1346     case PASS_THROUGH_ID:
1347       offset += dissect_pass_through(body_tree, tvb, offset, bodylen);
1348       break;
1349     default:
1350       proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
1351       offset += bodylen;
1352       break;
1353     }
1354   }
1355
1356   return offset;
1357 }
1358
1359 static guint
1360 get_dissect_hartip_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1361                        int offset, void *data _U_)
1362 {
1363   return tvb_get_ntohs(tvb, offset+6);
1364 }
1365
1366 static int
1367 dissect_hartip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1368 {
1369   return dissect_hartip_common(tvb, pinfo, tree, 0);
1370 }
1371
1372 static int
1373 dissect_hartip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1374                    void *data)
1375 {
1376   /* Simple hueristic check*/
1377   const gchar * msg_str = try_val_to_str(tvb_get_guint8(tvb, 1), hartip_message_type_values);
1378   if (!msg_str) {
1379     return 0;
1380   }
1381
1382   msg_str = try_val_to_str(tvb_get_guint8(tvb, 2), hartip_message_id_values);
1383   if (!msg_str) {
1384     return 0;
1385   }
1386
1387   tcp_dissect_pdus(tvb, pinfo, tree, hartip_desegment, HARTIP_HEADER_LENGTH,
1388                    get_dissect_hartip_len, dissect_hartip_pdu, data);
1389   return tvb_reported_length(tvb);
1390 }
1391
1392 static int
1393 dissect_hartip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1394                    void *data _U_)
1395 {
1396   gint offset = 0;
1397
1398   /* Simple hueristic check*/
1399   const gchar * msg_str = try_val_to_str(tvb_get_guint8(tvb, 1), hartip_message_type_values);
1400   if (!msg_str) {
1401     return 0;
1402   }
1403
1404   msg_str = try_val_to_str(tvb_get_guint8(tvb, 2), hartip_message_id_values);
1405   if (!msg_str) {
1406     return 0;
1407   }
1408
1409   while (tvb_reported_length_remaining(tvb, offset) >= HARTIP_HEADER_LENGTH)
1410     offset += dissect_hartip_common(tvb, pinfo, tree, offset);
1411
1412   return offset;
1413 }
1414
1415 void
1416 proto_register_hartip(void)
1417 {
1418   static hf_register_info hf[] = {
1419     /* HARTIP header elements. */
1420     { &hf_hartip_hdr_version,
1421       { "Version",           "hart_ip.version",
1422         FT_UINT8, BASE_DEC, NULL, 0x0,
1423         "HART_IP version number", HFILL }
1424     },
1425     { &hf_hartip_hdr_message_type,
1426       { "Message Type",           "hart_ip.message_type",
1427         FT_UINT8, BASE_DEC, VALS(hartip_message_type_values), 0,
1428         "HART_IP message type", HFILL }
1429     },
1430     { &hf_hartip_hdr_message_id,
1431       { "Message ID",           "hart_ip.message_id",
1432         FT_UINT8, BASE_DEC, VALS(hartip_message_id_values), 0,
1433         "HART_IP message id", HFILL }
1434     },
1435     { &hf_hartip_hdr_status,
1436       { "Status",           "hart_ip.status",
1437         FT_UINT8, BASE_DEC, NULL, 0x0,
1438         "HART_IP status field", HFILL }
1439     },
1440     { &hf_hartip_hdr_transaction_id,
1441       { "Sequence Number",           "hart_ip.transaction_id",
1442         FT_UINT16, BASE_DEC, NULL, 0x0,
1443         "HART_IP Sequence Number", HFILL }
1444     },
1445     { &hf_hartip_hdr_msg_length,
1446       { "Message Length",           "hart_ip.msg_length",
1447         FT_UINT16, BASE_DEC, NULL, 0x0,
1448         "HART_IP Message Length", HFILL }
1449     },
1450
1451     /* HARTIP Body elements   */
1452     { &hf_hartip_data,
1453       { "Message Data",           "hart_ip.data",
1454         FT_BYTES, BASE_NONE, NULL, 0x0,
1455         "HART_IP Message Data", HFILL }
1456     },
1457     { &hf_hartip_master_type,
1458       { "Host Type",           "hart_ip.session_init.master_type",
1459         FT_UINT8, BASE_DEC, VALS(hartip_master_type_values), 0xFF,
1460         "Session Host Type", HFILL }
1461     },
1462     { &hf_hartip_inactivity_close_timer,
1463       { "Inactivity Close Timer",           "hart_ip.session_init.inactivity_close_timer",
1464         FT_UINT32, BASE_DEC, NULL, 0x0,
1465         "Session Inactivity Close Timer", HFILL }
1466     },
1467     { &hf_hartip_error_code,
1468       { "Error",           "hart_ip.error.error_code",
1469         FT_UINT8, BASE_DEC, VALS(hartip_error_code_values), 0xFF,
1470         "Error Code", HFILL }
1471     },
1472
1473     /* HARTIP Pass-through commads. */
1474     { &hf_hartip_pt_preambles,
1475       { "Preambles",           "hart_ip.pt.preambles",
1476         FT_BYTES, BASE_NONE, NULL, 0x0,
1477         "Pass Through Preambles", HFILL }
1478     },
1479     { &hf_hartip_pt_delimiter,
1480       { "Delimter",           "hart_ip.pt.delimter",
1481         FT_UINT8, BASE_HEX, NULL, 0x0,
1482         "Pass Through Delimiter", HFILL }
1483     },
1484     { &hf_hartip_pt_short_addr,
1485       { "Short Address",           "hart_ip.pt.short_addr",
1486         FT_UINT8, BASE_DEC, NULL, 0x0,
1487         "Pass Through Short Address", HFILL }
1488     },
1489     { &hf_hartip_pt_long_addr,
1490       { "Long Address",           "hart_ip.pt.long_address",
1491         FT_BYTES, BASE_NONE, NULL, 0x0,
1492         "Pass Through Long Address", HFILL }
1493     },
1494     { &hf_hartip_pt_command,
1495       { "Command",           "hart_ip.pt.command",
1496         FT_UINT8, BASE_DEC, NULL, 0x0,
1497         "Pass Through Command", HFILL }
1498     },
1499     { &hf_hartip_pt_length,
1500       { "Length",           "hart_ip.pt.length",
1501         FT_UINT8, BASE_DEC, NULL, 0x0,
1502         "Pass Through Length", HFILL }
1503     },
1504     { &hf_hartip_pt_response_code,
1505       { "Response Code",           "hart_ip.pt.response_code",
1506         FT_UINT8, BASE_DEC, NULL, 0x0,
1507         "Pass Through Response Code", HFILL }
1508     },
1509     { &hf_hartip_pt_device_status,
1510       { "Device Status",           "hart_ip.pt.device_status",
1511         FT_UINT8, BASE_HEX, NULL, 0x0,
1512         "Pass Through Device Status", HFILL }
1513     },
1514     { &hf_hartip_pt_payload,
1515       { "Payload",           "hart_ip.pt.payload",
1516         FT_BYTES, BASE_NONE, NULL, 0x0,
1517         "Pass Through Payload", HFILL }
1518     },
1519     { &hf_hartip_pt_checksum,
1520       { "Checksum",           "hart_ip.pt.checksum",
1521         FT_UINT8, BASE_HEX, NULL, 0x0,
1522         "Pass Through Checksum", HFILL }
1523     },
1524
1525     /* add fields for universal commands. */
1526     /* command 0 */
1527     { &hf_hartip_pt_rsp_expansion_code,
1528       { "Expansion Code",           "hart_ip.pt.rsp.expansion_code",
1529         FT_UINT8, BASE_DEC, NULL, 0x0,
1530         NULL, HFILL }
1531     },
1532     { &hf_hartip_pt_rsp_expanded_device_type,
1533       { "Expanded Device Type",           "hart_ip.pt.rsp.expanded_device_type",
1534         FT_UINT16, BASE_HEX, NULL, 0x0,
1535         NULL, HFILL }
1536     },
1537     { &hf_hartip_pt_rsp_req_min_preambles,
1538       { "Minimum Number of Request Preambles",           "hart_ip.pt.rsp.req_min_preambles",
1539         FT_UINT8, BASE_DEC, NULL, 0x0,
1540         NULL, HFILL }
1541     },
1542     { &hf_hartip_pt_rsp_hart_protocol_major_rev,
1543       { "HART Universal Revision",           "hart_ip.pt.rsp.hart_univ_rev",
1544         FT_UINT8, BASE_DEC, NULL, 0x0,
1545         NULL, HFILL }
1546     },
1547     { &hf_hartip_pt_rsp_device_rev,
1548       { "Device Revision",           "hart_ip.pt.rsp.device_rev",
1549         FT_UINT8, BASE_DEC, NULL, 0x0,
1550         NULL, HFILL }
1551     },
1552     { &hf_hartip_pt_rsp_software_rev,
1553       { "Device Software Revision",           "hart_ip.pt.rsp.software_rev",
1554         FT_UINT8, BASE_DEC, NULL, 0x0,
1555         NULL, HFILL }
1556     },
1557     { &hf_hartip_pt_rsp_hardware_rev_physical_signal,
1558       { "Hardware Rev and Physical Signaling",           "hart_ip.pt.rsp.hardrev_and_physical_signal",
1559         FT_UINT8, BASE_HEX, NULL, 0x0,
1560         NULL, HFILL }
1561     },
1562     { &hf_hartip_pt_rsp_flage,
1563       { "Flags",           "hart_ip.pt.rsp.flags",
1564         FT_UINT8, BASE_HEX, NULL, 0x0,
1565         NULL, HFILL }
1566     },
1567     { &hf_hartip_pt_rsp_device_id,
1568       { "Device ID",           "hart_ip.pt.rsp.device_id",
1569         FT_BYTES, BASE_NONE, NULL, 0x0,
1570         NULL, HFILL }
1571     },
1572     { &hf_hartip_pt_rsp_rsp_min_preambles,
1573       { "Minimum Number of Response Preambles",           "hart_ip.pt.rsp.rsp_min_preambles",
1574         FT_UINT8, BASE_DEC, NULL, 0x0,
1575         NULL, HFILL }
1576     },
1577     { &hf_hartip_pt_rsp_max_device_variables,
1578       { "Maximum Number of Device Variables",           "hart_ip.pt.rsp.device_variables",
1579         FT_UINT8, BASE_DEC, NULL, 0x0,
1580         NULL, HFILL }
1581     },
1582     { &hf_hartip_pt_rsp_configuration_change_counter,
1583       { "Configuration Change Counter",           "hart_ip.pt.rsp.configure_change",
1584         FT_UINT16, BASE_DEC, NULL, 0x0,
1585         NULL, HFILL }
1586     },
1587     { &hf_hartip_pt_rsp_extended_device_status,
1588       { "Extended Device Status",           "hart_ip.pt.rsp.ext_device_status",
1589         FT_UINT8, BASE_HEX, NULL, 0x0,
1590         NULL, HFILL }
1591     },
1592     { &hf_hartip_pt_rsp_manufacturer_Identification_code,
1593       { "Manufacturer ID",           "hart_ip.pt.rsp.manufacturer_Id",
1594         FT_UINT16, BASE_DEC, NULL, 0x0,
1595         NULL, HFILL }
1596     },
1597     { &hf_hartip_pt_rsp_private_label,
1598       { "Private Label",           "hart_ip.pt.rsp.private_label",
1599         FT_UINT16, BASE_DEC, NULL, 0x0,
1600         NULL, HFILL }
1601     },
1602     { &hf_hartip_pt_rsp_device_profile,
1603       { "Device Profile",           "hart_ip.pt.rsp.device_profile",
1604         FT_UINT8, BASE_DEC, NULL, 0x0,
1605         NULL, HFILL }
1606     },
1607
1608     /* command 2 */
1609     { &hf_hartip_pt_rsp_pv_percent_range,
1610       { "PV Percent Range",           "hart_ip.pt.rsp.pv_percent_range",
1611         FT_FLOAT, BASE_NONE, NULL, 0x0,
1612         NULL, HFILL }
1613     },
1614
1615     /* command 3 */
1616     { &hf_hartip_pt_rsp_pv_loop_current,
1617       { "PV Loop Current",           "hart_ip.pt.rsp.pv_loop_current",
1618         FT_FLOAT, BASE_NONE, NULL, 0x0,
1619         NULL, HFILL }
1620     },
1621     { &hf_hartip_pt_rsp_pv_units,
1622       { "PV Units",           "hart_ip.pt.rsp.pv_units",
1623         FT_UINT8, BASE_DEC, NULL, 0x0,
1624         NULL, HFILL }
1625     },
1626     { &hf_hartip_pt_rsp_pv,
1627       { "PV",           "hart_ip.pt.rsp.pv",
1628         FT_FLOAT, BASE_NONE, NULL, 0x0,
1629         NULL, HFILL }
1630     },
1631     { &hf_hartip_pt_rsp_sv_units,
1632       { "SV Units",           "hart_ip.pt.rsp.sv_units",
1633         FT_UINT8, BASE_DEC, NULL, 0x0,
1634         NULL, HFILL }
1635     },
1636     { &hf_hartip_pt_rsp_sv,
1637       { "SV",           "hart_ip.pt.rsp.sv",
1638         FT_FLOAT, BASE_NONE, NULL, 0x0,
1639         NULL, HFILL }
1640     },
1641     { &hf_hartip_pt_rsp_tv_units,
1642       { "TV Units",           "hart_ip.pt.rsp.tv_units",
1643         FT_UINT8, BASE_DEC, NULL, 0x0,
1644         NULL, HFILL }
1645     },
1646     { &hf_hartip_pt_rsp_tv,
1647       { "TV",           "hart_ip.pt.rsp.tv",
1648         FT_FLOAT, BASE_NONE, NULL, 0x0,
1649         NULL, HFILL }
1650     },
1651     { &hf_hartip_pt_rsp_qv_units,
1652       { "QV Units",           "hart_ip.pt.rsp.qv_units",
1653         FT_UINT8, BASE_DEC, NULL, 0x0,
1654         NULL, HFILL }
1655     },
1656     { &hf_hartip_pt_rsp_qv,
1657       { "QV",           "hart_ip.pt.rsp.qv",
1658         FT_FLOAT, BASE_NONE, NULL, 0x0,
1659         NULL, HFILL }
1660     },
1661
1662     /* command 7 */
1663     { &hf_hartip_pt_rsp_loop_current_mode,
1664       { "Loop Current Mode",                     "hart_ip.pt.rsp.loop_current_mode",
1665         FT_UINT8, BASE_HEX, NULL, 0x0,
1666         NULL, HFILL }
1667     },
1668
1669     /* command 8 */
1670     { &hf_hartip_pt_rsp_primary_var_classify,
1671       { "Primary Variable Classification",       "hart_ip.pt.rsp.primary_variable_classification",
1672         FT_UINT8, BASE_HEX, NULL, 0x0,
1673         NULL, HFILL }
1674     },
1675     { &hf_hartip_pt_rsp_secondary_var_classify,
1676       { "Secondary Variable Classification",     "hart_ip.pt.rsp.secondary_variable_classification",
1677         FT_UINT8, BASE_HEX, NULL, 0x0,
1678         NULL, HFILL }
1679     },
1680     { &hf_hartip_pt_rsp_tertiary_var_classify,
1681       { "Tertiary Variable Classification",      "hart_ip.pt.rsp.tertiary_variable_classification",
1682         FT_UINT8, BASE_HEX, NULL, 0x0,
1683         NULL, HFILL }
1684     },
1685     { &hf_hartip_pt_rsp_quaternary_var_classify,
1686       { "Quaternary Variable Classification",    "hart_ip.pt.rsp.quaternary_variable_classification",
1687         FT_UINT8, BASE_HEX, NULL, 0x0,
1688         NULL, HFILL }
1689     },
1690
1691     /* command 9 */
1692     { &hf_hartip_pt_rsp_slot0_device_var,
1693       { "Slot0 Device Variable",           "hart_ip.pt.rsp.slot0_device_var",
1694         FT_UINT8, BASE_DEC, NULL, 0x0,
1695         NULL, HFILL }
1696     },
1697     { &hf_hartip_pt_rsp_slot0_device_var_classify,
1698       { "Slot0 Device Variable Classification",  "hart_ip.pt.rsp.slot0_device_var_classification",
1699         FT_UINT8, BASE_DEC, NULL, 0x0,
1700         NULL, HFILL }
1701     },
1702     { &hf_hartip_pt_rsp_slot0_units,
1703       { "Slot0 Units",           "hart_ip.pt.rsp.slot0_units",
1704         FT_UINT8, BASE_DEC, NULL, 0x0,
1705         NULL, HFILL }
1706     },
1707     { &hf_hartip_pt_rsp_slot0_device_var_value,
1708       { "Slot0 Device Variable Value",           "hart_ip.pt.rsp.slot0_device_var_value",
1709         FT_FLOAT, BASE_NONE, NULL, 0x0,
1710         NULL, HFILL }
1711     },
1712     { &hf_hartip_pt_rsp_slot0_device_var_status,
1713       { "Slot0 Device Variable Status",           "hart_ip.pt.rsp.slot0_device_var_status",
1714         FT_UINT8, BASE_HEX, NULL, 0x0,
1715         NULL, HFILL }
1716     },
1717     { &hf_hartip_pt_rsp_slot1_device_var,
1718       { "Slot1 Device Variable",           "hart_ip.pt.rsp.slot1_device_var",
1719         FT_UINT8, BASE_DEC, NULL, 0x0,
1720         NULL, HFILL }
1721     },
1722     { &hf_hartip_pt_rsp_slot1_device_var_classify,
1723       { "Slot1 Device Variable Classification",           "hart_ip.pt.rsp.slot1_device_var_classify",
1724         FT_UINT8, BASE_DEC, NULL, 0x0,
1725         NULL, HFILL }
1726     },
1727     { &hf_hartip_pt_rsp_slot1_units,
1728       { "Slot1 Units",           "hart_ip.pt.rsp.slot1_units",
1729         FT_UINT8, BASE_DEC, NULL, 0x0,
1730         NULL, HFILL }
1731     },
1732     { &hf_hartip_pt_rsp_slot1_device_var_value,
1733       { "Slot1 Device Variable Value",           "hart_ip.pt.rsp.slot1_device_var_value",
1734         FT_FLOAT, BASE_NONE, NULL, 0x0,
1735         NULL, HFILL }
1736     },
1737     { &hf_hartip_pt_rsp_slot1_device_var_status,
1738       { "Slot1 Device Variable Status",           "hart_ip.pt.rsp.slot1_device_var_status",
1739         FT_UINT8, BASE_HEX, NULL, 0x0,
1740         NULL, HFILL }
1741     },
1742     { &hf_hartip_pt_rsp_slot2_device_var,
1743       { "Slot2 Device Variable",           "hart_ip.pt.rsp.slot2_device_var",
1744         FT_UINT8, BASE_DEC, NULL, 0x0,
1745         NULL, HFILL }
1746     },
1747     { &hf_hartip_pt_rsp_slot2_device_var_classify,
1748       { "Slot2 Device Variable Classification",           "hart_ip.pt.rsp.slot2_device_var_classify",
1749         FT_UINT8, BASE_DEC, NULL, 0x0,
1750         NULL, HFILL }
1751     },
1752     { &hf_hartip_pt_rsp_slot2_units,
1753       { "Slot2 Units",           "hart_ip.pt.rsp.slot2_units",
1754         FT_UINT8, BASE_DEC, NULL, 0x0,
1755         NULL, HFILL }
1756     },
1757     { &hf_hartip_pt_rsp_slot2_device_var_value,
1758       { "Slot2 Device Variable Value",           "hart_ip.pt.rsp.slot2_device_var_value",
1759         FT_FLOAT, BASE_NONE, NULL, 0x0,
1760         NULL, HFILL }
1761     },
1762     { &hf_hartip_pt_rsp_slot2_device_var_status,
1763       { "Slot2 Device Variable Status",           "hart_ip.pt.rsp.slot2_device_var_status",
1764         FT_UINT8, BASE_HEX, NULL, 0x0,
1765         NULL, HFILL }
1766     },
1767     { &hf_hartip_pt_rsp_slot3_device_var,
1768       { "Slot3 Device Variable",           "hart_ip.pt.rsp.slot3_device_var",
1769         FT_UINT8, BASE_DEC, NULL, 0x0,
1770         NULL, HFILL }
1771     },
1772     { &hf_hartip_pt_rsp_slot3_device_var_classify,
1773       { "Slot3 Device Variable Classification",           "hart_ip.pt.rsp.slot3_device_var_classify",
1774         FT_UINT8, BASE_DEC, NULL, 0x0,
1775         NULL, HFILL }
1776     },
1777     { &hf_hartip_pt_rsp_slot3_units,
1778       { "Slot3 Units",           "hart_ip.pt.rsp.slot3_units",
1779         FT_UINT8, BASE_DEC, NULL, 0x0,
1780         NULL, HFILL }
1781     },
1782     { &hf_hartip_pt_rsp_slot3_device_var_value,
1783       { "Slot3 Device Variable Value",           "hart_ip.pt.rsp.slot3_device_var_value",
1784         FT_FLOAT, BASE_NONE, NULL, 0x0,
1785         NULL, HFILL }
1786     },
1787     { &hf_hartip_pt_rsp_slot3_device_var_status,
1788       { "Slot3 Device Variable Status",           "hart_ip.pt.rsp.slot3_device_var_status",
1789         FT_UINT8, BASE_HEX, NULL, 0x0,
1790         NULL, HFILL }
1791     },
1792     { &hf_hartip_pt_rsp_slot4_device_var,
1793       { "Slot4 Device Variable",           "hart_ip.pt.rsp.slot4_device_var",
1794         FT_UINT8, BASE_DEC, NULL, 0x0,
1795         NULL, HFILL }
1796     },
1797     { &hf_hartip_pt_rsp_slot4_device_var_classify,
1798       { "Slot4 Device Variable Classification",           "hart_ip.pt.rsp.slot4_device_var_classify",
1799         FT_UINT8, BASE_DEC, NULL, 0x0,
1800         NULL, HFILL }
1801     },
1802     { &hf_hartip_pt_rsp_slot4_units,
1803       { "Slot4 Units",           "hart_ip.pt.rsp.slot4_units",
1804         FT_UINT8, BASE_DEC, NULL, 0x0,
1805         NULL, HFILL }
1806     },
1807     { &hf_hartip_pt_rsp_slot4_device_var_value,
1808       { "Slot4 Device Variable Value",           "hart_ip.pt.rsp.slot4_device_var_value",
1809         FT_FLOAT, BASE_NONE, NULL, 0x0,
1810         NULL, HFILL }
1811     },
1812     { &hf_hartip_pt_rsp_slot4_device_var_status,
1813       { "Slot4 Device Variable Status",           "hart_ip.pt.rsp.slot4_device_var_status",
1814         FT_UINT8, BASE_HEX, NULL, 0x0,
1815         NULL, HFILL }
1816     },
1817     { &hf_hartip_pt_rsp_slot5_device_var,
1818       { "Slot5 Device Variable",           "hart_ip.pt.rsp.slot5_device_var",
1819         FT_UINT8, BASE_DEC, NULL, 0x0,
1820         NULL, HFILL }
1821     },
1822     { &hf_hartip_pt_rsp_slot5_device_var_classify,
1823       { "Slot5 Device Variable Classification",           "hart_ip.pt.rsp.slot5_device_var_classify",
1824         FT_UINT8, BASE_DEC, NULL, 0x0,
1825         NULL, HFILL }
1826     },
1827     { &hf_hartip_pt_rsp_slot5_units,
1828       { "Slot5 Units",           "hart_ip.pt.rsp.slot5_units",
1829         FT_UINT8, BASE_DEC, NULL, 0x0,
1830         NULL, HFILL }
1831     },
1832     { &hf_hartip_pt_rsp_slot5_device_var_value,
1833       { "Slot5 Device Variable Value",           "hart_ip.pt.rsp.slot5_device_var_value",
1834         FT_FLOAT, BASE_NONE, NULL, 0x0,
1835         NULL, HFILL }
1836     },
1837     { &hf_hartip_pt_rsp_slot5_device_var_status,
1838       { "Slot5 Device Variable Status",           "hart_ip.pt.rsp.slot5_device_var_status",
1839         FT_UINT8, BASE_HEX, NULL, 0x0,
1840         NULL, HFILL }
1841     },
1842     { &hf_hartip_pt_rsp_slot6_device_var,
1843       { "Slot6 Device Variable",           "hart_ip.pt.rsp.slot6_device_var",
1844         FT_UINT8, BASE_DEC, NULL, 0x0,
1845         NULL, HFILL }
1846     },
1847     { &hf_hartip_pt_rsp_slot6_device_var_classify,
1848       { "Slot6 Device Variable Classification",           "hart_ip.pt.rsp.slot6_device_var_classify",
1849         FT_UINT8, BASE_DEC, NULL, 0x0,
1850         NULL, HFILL }
1851     },
1852     { &hf_hartip_pt_rsp_slot6_units,
1853       { "Slot6 Units",           "hart_ip.pt.rsp.slot6_units",
1854         FT_UINT8, BASE_DEC, NULL, 0x0,
1855         NULL, HFILL }
1856     },
1857     { &hf_hartip_pt_rsp_slot6_device_var_value,
1858       { "Slot6 Device Variable Value",           "hart_ip.pt.rsp.slot6_device_var_value",
1859         FT_FLOAT, BASE_NONE, NULL, 0x0,
1860         NULL, HFILL }
1861     },
1862     { &hf_hartip_pt_rsp_slot6_device_var_status,
1863       { "Slot6 Device Variable Status",           "hart_ip.pt.rsp.slot6_device_var_status",
1864         FT_UINT8, BASE_HEX, NULL, 0x0,
1865         NULL, HFILL }
1866     },
1867     { &hf_hartip_pt_rsp_slot7_device_var,
1868       { "Slot7 Device Variable",           "hart_ip.pt.rsp.slot7_device_var",
1869         FT_UINT8, BASE_DEC, NULL, 0x0,
1870         NULL, HFILL }
1871     },
1872     { &hf_hartip_pt_rsp_slot7_device_var_classify,
1873       { "Slot7 Device Variable Classification",           "hart_ip.pt.rsp.slot7_device_var_classify",
1874         FT_UINT8, BASE_DEC, NULL, 0x0,
1875         NULL, HFILL }
1876     },
1877     { &hf_hartip_pt_rsp_slot7_units,
1878       { "Slot7 Units",           "hart_ip.pt.rsp.slot7_units",
1879         FT_UINT8, BASE_DEC, NULL, 0x0,
1880         NULL, HFILL }
1881     },
1882     { &hf_hartip_pt_rsp_slot7_device_var_value,
1883       { "Slot7 Device Variable Value",           "hart_ip.pt.rsp.slot7_device_var_value",
1884         FT_FLOAT, BASE_NONE, NULL, 0x0,
1885         NULL, HFILL }
1886     },
1887     { &hf_hartip_pt_rsp_slot7_device_var_status,
1888       { "Slot7 Device Variable Status",           "hart_ip.pt.rsp.slot7_device_var_status",
1889         FT_UINT8, BASE_HEX, NULL, 0x0,
1890         NULL, HFILL }
1891     },
1892     { &hf_hartip_pt_rsp_slot0_timestamp,
1893       { "Slot0 Data TimeStamp",           "hart_ip.pt.rsp.slot0_data_timestamp",
1894         FT_BYTES, BASE_NONE, NULL, 0x0,
1895         NULL, HFILL }
1896     },
1897
1898     /* command 13 */
1899     { &hf_hartip_pt_rsp_packed_descriptor,
1900       { "Descriptor",           "hart_ip.pt.rsp.descriptor",
1901         FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
1902         NULL, HFILL }
1903     },
1904     { &hf_hartip_pt_rsp_day,
1905       { "Day",           "hart_ip.pt.rsp.day",
1906         FT_UINT8, BASE_DEC, NULL, 0x0,
1907         NULL, HFILL }
1908     },
1909     { &hf_hartip_pt_rsp_month,
1910       { "Month",           "hart_ip.pt.rsp.month",
1911         FT_UINT8, BASE_DEC, NULL, 0x0,
1912         NULL, HFILL }
1913     },
1914     { &hf_hartip_pt_rsp_year,
1915       { "Year",           "hart_ip.pt.rsp.year",
1916         FT_UINT8, BASE_DEC, NULL, 0x0,
1917         NULL, HFILL }
1918     },
1919
1920     /* command 14 */
1921     { &hf_hartip_pt_rsp_transducer_serial_number,
1922       { "Transducer Serail Number",              "hart_ip.pt.rsp.transducer_serail_number",
1923         FT_BYTES, BASE_NONE, NULL, 0x0,
1924         NULL, HFILL }
1925     },
1926     { &hf_hartip_pt_rsp_transducer_limit_min_span_units,
1927       { "Transducer Limit Min Span Units",  "hart_ip.pt.rsp.transducer_limit_min_span_units",
1928         FT_UINT8, BASE_HEX, NULL, 0x0,
1929         NULL, HFILL }
1930     },
1931     { &hf_hartip_pt_rsp_upper_transducer_limit,
1932       { "Upper Transducer Limit",                "hart_ip.pt.rsp.upper_transducer_limit",
1933         FT_FLOAT, BASE_NONE, NULL, 0x0,
1934         NULL, HFILL }
1935     },
1936     { &hf_hartip_pt_rsp_lower_transducer_limit,
1937       { "Lower Transducer Limit",                "hart_ip.pt.rsp.lower_transducer_limit",
1938         FT_FLOAT, BASE_NONE, NULL, 0x0,
1939         NULL, HFILL }
1940     },
1941     { &hf_hartip_pt_rsp_minimum_span,
1942       { "Minimum Span",                          "hart_ip.pt.rsp.minimum_span",
1943         FT_FLOAT, BASE_NONE, NULL, 0x0,
1944         NULL, HFILL }
1945     },
1946
1947     /* command 15 */
1948     { &hf_hartip_pt_rsp_pv_alarm_selection_code,
1949       { "PV Alarm Selection Code",                     "hart_ip.pt.rsp.pv_alarm_selection_code",
1950         FT_UINT8, BASE_HEX, NULL, 0x0,
1951         NULL, HFILL }
1952     },
1953     { &hf_hartip_pt_rsp_pv_transfer_function_code,
1954       { "PV Transfer Function Code",                   "hart_ip.pt.rsp.pv_transfer_function_code",
1955         FT_UINT8, BASE_HEX, NULL, 0x0,
1956         NULL, HFILL }
1957     },
1958     { &hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units,
1959       { "PV Upper and Lower Range Values Units",  "hart_ip.pt.rsp.pv_upper_and_lower_range_values_units",
1960         FT_UINT8, BASE_HEX, NULL, 0x0,
1961         NULL, HFILL }
1962     },
1963     { &hf_hartip_pt_rsp_pv_upper_range_value,
1964       { "PV Upper Range Value",                        "hart_ip.pt.rsp.pv_upper_range_value",
1965         FT_FLOAT, BASE_NONE, NULL, 0x0,
1966         NULL, HFILL }
1967     },
1968     { &hf_hartip_pt_rsp_pv_lower_range_value,
1969       { "PV Lower Range Value",                        "hart_ip.pt.rsp.pv_lower_range_value",
1970         FT_FLOAT, BASE_NONE, NULL, 0x0,
1971         NULL, HFILL }
1972     },
1973     { &hf_hartip_pt_rsp_pv_damping_value,
1974       { "PV Damping Value",                            "hart_ip.pt.rsp.pv_damping_value",
1975         FT_FLOAT, BASE_NONE, NULL, 0x0,
1976         NULL, HFILL }
1977     },
1978     { &hf_hartip_pt_rsp_write_protect_code,
1979       { "Write Protect Code",                          "hart_ip.pt.rsp.write_protect_code",
1980         FT_UINT8, BASE_HEX, NULL, 0x0,
1981         NULL, HFILL }
1982     },
1983     { &hf_hartip_pt_rsp_reserved,
1984       { "Reserved",                                    "hart_ip.pt.rsp.reserved",
1985         FT_UINT8, BASE_HEX, NULL, 0x0,
1986         NULL, HFILL }
1987     },
1988     { &hf_hartip_pt_rsp_pv_analog_channel_flags,
1989       { "PV Analog Channel Flags",                     "hart_ip.pt.rsp.pv_analog_channel_flags",
1990         FT_UINT8, BASE_HEX, NULL, 0x0,
1991         NULL, HFILL }
1992     },
1993
1994     /* command 16 and 19 */
1995     { &hf_hartip_pt_rsp_final_assembly_number,
1996       { "Final Assembly Number",                       "hart_ip.pt.rsp.final_assembly_numbe",
1997         FT_BYTES, BASE_NONE, NULL, 0x0,
1998         NULL, HFILL }
1999     },
2000
2001     /* Tag */
2002     { &hf_hartip_pt_rsp_tag,
2003       { "Tag",           "hart_ip.pt.rsp.tag",
2004         FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2005         NULL, HFILL }
2006     },
2007
2008     /* Message */
2009     { &hf_hartip_pt_rsp_message,
2010       { "Message",           "hart_ip.pt.rsp.message",
2011         FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2012         NULL, HFILL }
2013     },
2014
2015     /* command 48 */
2016     { &hf_hartip_pt_rsp_device_sp_status,
2017       { "Device-Specific Status",           "hart_ip.pt.rsp.device_sp_status",
2018         FT_BYTES, BASE_NONE, NULL, 0x0,
2019         NULL, HFILL }
2020     },
2021     { &hf_hartip_pt_rsp_device_op_mode,
2022       { "Device Operating Mode",           "hart_ip.pt.rsp.device_op_mode",
2023         FT_UINT8, BASE_DEC, NULL, 0x0,
2024         NULL, HFILL }
2025     },
2026     { &hf_hartip_pt_rsp_standardized_status_0,
2027       { "Standardized Status 0",           "hart_ip.pt.rsp.standardized_status_0",
2028         FT_UINT8, BASE_HEX, NULL, 0x0,
2029         NULL, HFILL }
2030     },
2031     { &hf_hartip_pt_rsp_standardized_status_1,
2032       { "Standardized Status 1",           "hart_ip.pt.rsp.standardized_status_1",
2033         FT_UINT8, BASE_HEX, NULL, 0x0,
2034         NULL, HFILL }
2035     },
2036     { &hf_hartip_pt_rsp_analog_channel_saturated,
2037       { "Analog Channel Saturated",           "hart_ip.pt.rsp.analog_channel_saturated",
2038         FT_UINT8, BASE_DEC, NULL, 0x0,
2039         NULL, HFILL }
2040     },
2041     { &hf_hartip_pt_rsp_standardized_status_2,
2042       { "Standardized Status 2",           "hart_ip.pt.rsp.standardized_status_2",
2043         FT_UINT8, BASE_HEX, NULL, 0x0,
2044         NULL, HFILL }
2045     },
2046     { &hf_hartip_pt_rsp_standardized_status_3,
2047       { "Standardized Status 3",           "hart_ip.pt.rsp.standardized_status_3",
2048         FT_UINT8, BASE_HEX, NULL, 0x0,
2049         NULL, HFILL }
2050     },
2051     { &hf_hartip_pt_rsp_analog_channel_fixed,
2052       { "Analog Channel Fixed",           "hart_ip.pt.rsp.analog_channel_fixed",
2053         FT_UINT8, BASE_DEC, NULL, 0x0,
2054         NULL, HFILL }
2055     },
2056
2057     /* command 77 */
2058     { &hf_hartip_pt_rsp_io_card,
2059       { "IO Card",                     "hart_ip.pt.rsp.io_card",
2060         FT_UINT8, BASE_DEC, NULL, 0x0,
2061         NULL, HFILL }
2062     },
2063     { &hf_hartip_pt_rsp_channel,
2064       { "Channel",                     "hart_ip.pt.rsp.channel",
2065         FT_UINT8, BASE_DEC, NULL, 0x0,
2066         NULL, HFILL }
2067     },
2068     { &hf_hartip_pt_rsp_embedded_cmd_delimiter,
2069       { "Embedded Command Delimter",   "hart_ip.pt.rsp.embedded_command_delimter",
2070         FT_UINT8, BASE_HEX, NULL, 0x0,
2071         NULL, HFILL }
2072     },
2073     { &hf_hartip_pt_rsp_poll_address,
2074       { "Poll Address",                "hart_ip.pt.rsp.poll_address",
2075         FT_UINT8, BASE_DEC, NULL, 0x0,
2076         NULL, HFILL }
2077     },
2078     { &hf_hartip_pt_rsp_embedded_cmd,
2079       { "Embedded Command",            "hart_ip.pt.rsp.embedded_command",
2080         FT_UINT8, BASE_DEC, NULL, 0x0,
2081         NULL, HFILL }
2082     },
2083
2084     /* command 178 */
2085     { &hf_hartip_pt_rsp_number_of_commands,
2086       { "Number of Commands",          "hart_ip.pt.rsp.number_of_commands",
2087         FT_UINT8, BASE_DEC, NULL, 0x0,
2088         NULL, HFILL }
2089     },
2090     /* command 31 and 178 */
2091     { &hf_hartip_pt_rsp_command_number,
2092       { "Command number",              "hart_ip.pt.rsp.command_number",
2093         FT_UINT16, BASE_DEC, NULL, 0x0,
2094         NULL, HFILL }
2095     },
2096     { &hf_hartip_pt_rsp_data,
2097       { "Data",                        "hart_ip.pt.rsp.data",
2098         FT_BYTES, BASE_NONE, NULL, 0x0,
2099         NULL, HFILL }
2100     },
2101     /* command 77 and 178 */
2102     { &hf_hartip_pt_rsp_command_byte_count,
2103       { "Command byte count",          "hart_ip.pt.rsp.command_byte_count",
2104         FT_UINT8, BASE_DEC, NULL, 0x0,
2105         NULL, HFILL }
2106     },
2107
2108     /* command 203 */
2109     { &hf_hartip_pt_rsp_index_of_first_discrete_var,
2110       { "Index of First Discrete Variable",           "hart_ip.pt.rsp.index_of_first_discrete_var",
2111         FT_UINT16, BASE_DEC, NULL, 0x0,
2112         NULL, HFILL }
2113     },
2114     { &hf_hartip_pt_rsp_number_of_discrete_vars,
2115       { "Number of Discrete Variables",               "hart_ip.pt.rsp.number_of_discrete_vars",
2116         FT_UINT8, BASE_HEX, NULL, 0x0,
2117         NULL, HFILL }
2118     },
2119     { &hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
2120       { "TimeStamp for Most Recent Discrete Change",  "hart_ip.pt.rsp.timestamp_for_most_recent_discrete_change",
2121         FT_BYTES, BASE_NONE, NULL, 0x0,
2122         NULL, HFILL }
2123     },
2124     { &hf_hartip_pt_rsp_slot0_discrete_var_state,
2125       { "Slot0 Discrete Variable State",              "hart_ip.pt.rsp.slot0_discrete_var_state",
2126         FT_UINT16, BASE_DEC, NULL, 0x0,
2127         NULL, HFILL }
2128     },
2129     { &hf_hartip_pt_rsp_slot0_discrete_var_status,
2130       { "Slot0 Discrete Variable Status",             "hart_ip.pt.rsp.slot0_discrete_var_status",
2131         FT_UINT8, BASE_HEX, NULL, 0x0,
2132         NULL, HFILL }
2133     },
2134     { &hf_hartip_pt_rsp_slot1_discrete_var_state,
2135       { "Slot1 Discrete Variable State",              "hart_ip.pt.rsp.slot1_discrete_var_state",
2136         FT_UINT16, BASE_DEC, NULL, 0x0,
2137         NULL, HFILL }
2138     },
2139     { &hf_hartip_pt_rsp_slot1_discrete_var_status,
2140       { "Slot1 Discrete Variable Status",             "hart_ip.pt.rsp.slot1_discrete_var_status",
2141         FT_UINT8, BASE_HEX, NULL, 0x0,
2142         NULL, HFILL }
2143     },
2144     { &hf_hartip_pt_rsp_slot2_discrete_var_state,
2145       { "Slot2 Discrete Variable State",              "hart_ip.pt.rsp.slot2_discrete_var_state",
2146         FT_UINT16, BASE_DEC, NULL, 0x0,
2147         NULL, HFILL }
2148     },
2149     { &hf_hartip_pt_rsp_slot2_discrete_var_status,
2150       { "Slot2 Discrete Variable Status",             "hart_ip.pt.rsp.slot2_discrete_var_status",
2151         FT_UINT8, BASE_HEX, NULL, 0x0,
2152         NULL, HFILL }
2153     },
2154     { &hf_hartip_pt_rsp_slot3_discrete_var_state,
2155       { "Slot3 Discrete Variable State",              "hart_ip.pt.rsp.slot3_discrete_var_state",
2156         FT_UINT16, BASE_DEC, NULL, 0x0,
2157         NULL, HFILL }
2158     },
2159     { &hf_hartip_pt_rsp_slot3_discrete_var_status,
2160       { "Slot3 Discrete Variable Status",             "hart_ip.pt.rsp.slot3_discrete_var_status",
2161         FT_UINT8, BASE_HEX, NULL, 0x0,
2162         NULL, HFILL }
2163     },
2164     { &hf_hartip_pt_rsp_slot4_discrete_var_state,
2165       { "Slot4 Discrete Variable State",              "hart_ip.pt.rsp.slot4_discrete_var_state",
2166         FT_UINT16, BASE_DEC, NULL, 0x0,
2167         NULL, HFILL }
2168     },
2169     { &hf_hartip_pt_rsp_slot4_discrete_var_status,
2170       { "Slot4 Discrete Variable Status",             "hart_ip.pt.rsp.slot4_discrete_var_status",
2171         FT_UINT8, BASE_HEX, NULL, 0x0,
2172         NULL, HFILL }
2173     },
2174     { &hf_hartip_pt_rsp_slot5_discrete_var_state,
2175       { "Slot5 Discrete Variable State",              "hart_ip.pt.rsp.slot5_discrete_var_state",
2176         FT_UINT16, BASE_DEC, NULL, 0x0,
2177         NULL, HFILL }
2178     },
2179     { &hf_hartip_pt_rsp_slot5_discrete_var_status,
2180       { "Slot5 Discrete Variable Status",             "hart_ip.pt.rsp.slot5_discrete_var_status",
2181         FT_UINT8, BASE_HEX, NULL, 0x0,
2182         NULL, HFILL }
2183     }
2184   };
2185
2186   static gint *ett[] = {
2187     &ett_hartip,
2188     &ett_hartip_hdr,
2189     &ett_hartip_body
2190   };
2191
2192   static ei_register_info ei[] = {
2193      { &ei_hartip_data_none, { "hart_ip.data.none", PI_PROTOCOL, PI_NOTE, "No data", EXPFILL }},
2194      { &ei_hartip_data_unexpected, { "hart_ip.data.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected message body", EXPFILL }},
2195   };
2196
2197   module_t *hartip_module;
2198   expert_module_t* expert_hartip;
2199
2200   proto_hartip = proto_register_protocol("HART_IP Protocol", "HART_IP", "hart_ip");
2201   proto_register_field_array(proto_hartip, hf, array_length(hf));
2202   proto_register_subtree_array(ett, array_length(ett));
2203   expert_hartip = expert_register_protocol(proto_hartip);
2204   expert_register_field_array(expert_hartip, ei, array_length(ei));
2205
2206   hartip_module = prefs_register_protocol(proto_hartip, NULL);
2207   prefs_register_bool_preference(hartip_module, "desegment",
2208                                   "Desegment all HART-IP messages spanning multiple TCP segments",
2209                                   "Whether the HART-IP dissector should desegment all messages spanning multiple TCP segments",
2210                                   &hartip_desegment);
2211
2212   hartip_tap = register_tap("hart_ip");
2213 }
2214
2215 void
2216 proto_reg_handoff_hartip(void)
2217 {
2218   hartip_tcp_handle = create_dissector_handle(dissect_hartip_tcp, proto_hartip);
2219   hartip_udp_handle = create_dissector_handle(dissect_hartip_udp, proto_hartip);
2220   dissector_add_uint_with_preference("udp.port", HARTIP_PORT, hartip_udp_handle);
2221   dissector_add_uint_with_preference("tcp.port", HARTIP_PORT, hartip_tcp_handle);
2222
2223   stats_tree_register("hart_ip", "hart_ip", "HART-IP", 0,
2224                       hartip_stats_tree_packet, hartip_stats_tree_init, NULL);
2225 }
2226
2227 /*
2228  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2229  *
2230  * Local variables:
2231  * c-basic-offset: 2
2232  * tab-width: 8
2233  * indent-tabs-mode: nil
2234  * End:
2235  *
2236  * vi: set shiftwidth=2 tabstop=8 expandtab:
2237  * :indentSize=2:tabSize=8:noTabs=true:
2238  */
2239