Coverage Report

Created: 2025-02-15 06:25

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