Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-hartip.c
Line
Count
Source
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
136
#define HARTIP_HEADER_LENGTH     8
243
32
#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
42
#define SESSION_INITIATE_ID       0
257
0
#define SESSION_CLOSE_ID          1
258
0
#define KEEP_ALIVE_ID             2
259
13
#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
31
#define ERROR_MSG_TYPE         3
266
27
#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
5
#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(pinfo->pool, 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
11
{
422
11
  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
11
  } else {
428
11
    proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
429
11
  }
430
431
11
  return bodylen;
432
11
}
433
434
static int
435
dissect_error(proto_tree *body_tree, tvbuff_t *tvb, int offset, int bodylen)
436
2
{
437
2
  if (bodylen == 1) {
438
0
    proto_tree_add_item(body_tree, hf_hartip_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
439
2
  } else {
440
2
    proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
441
2
  }
442
443
2
  return bodylen;
444
2
}
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
30
{
463
30
  proto_tree_add_item(tree, hf, tvb, offset, 1, ENC_BIG_ENDIAN);
464
30
  return 1;
465
30
}
466
467
static int
468
dissect_short(proto_tree *tree, int hf, tvbuff_t *tvb, int offset)
469
9
{
470
9
  proto_tree_add_item(tree, hf, tvb, offset, 2, ENC_BIG_ENDIAN);
471
9
  return 2;
472
9
}
473
474
static int
475
dissect_float(proto_tree *tree, int hf, tvbuff_t *tvb, int offset)
476
6
{
477
6
  proto_tree_add_item(tree, hf, tvb, offset, 4, ENC_BIG_ENDIAN);
478
6
  return 4;
479
6
}
480
481
static int
482
dissect_packAscii(proto_tree *tree, packet_info* pinfo, int hf, tvbuff_t *tvb, int offset, int len)
483
4
{
484
4
  uint16_t    usIdx;
485
4
  uint16_t    usGroupCnt;
486
4
  uint16_t    usMaxGroups;      /* Number of 4 byte groups to pack. */
487
4
  uint16_t    usMask;
488
4
  int         iIndex;
489
4
  int         i   = 0;
490
4
  uint16_t    buf[4];
491
4
  uint8_t    *tmp;
492
4
  char       *str = NULL;
493
494
4
  tmp = (uint8_t *)wmem_alloc0(pinfo->pool, len);
495
4
  tvb_memcpy(tvb, tmp, offset, len);
496
497
  /* Maximum possible unpacked length = (len / 3) * 4 */
498
4
  str = (char *)wmem_alloc(pinfo->pool, ((len / 3) * 4)+1);
499
500
4
  iIndex = 0;
501
4
  usMaxGroups = (uint16_t)(len / 3);
502
12
  for (usGroupCnt = 0; usGroupCnt < usMaxGroups; usGroupCnt++) {
503
    /*
504
     * First unpack 3 bytes into a group of 4 bytes, clearing bits 6 & 7.
505
     */
506
8
    buf[0] = (uint16_t)(tmp[iIndex] >> 2);
507
8
    buf[1] = (uint16_t)(((tmp[iIndex] << 4) & 0x30) | (tmp[iIndex + 1] >> 4));
508
8
    buf[2] = (uint16_t)(((tmp[iIndex + 1] << 2) & 0x3C) | (tmp[iIndex + 2] >> 6));
509
8
    buf[3] = (uint16_t)(tmp[iIndex + 2] & 0x3F);
510
8
    iIndex += 3;
511
512
    /*
513
     * Now transfer to unpacked area, setting bit 6 to complement of bit 5.
514
     */
515
40
    for (usIdx = 0; usIdx < 4; usIdx++) {
516
32
      usMask = (uint16_t)(((buf[usIdx] & 0x20) << 1) ^ 0x40);
517
32
      DISSECTOR_ASSERT(i < 256);
518
32
      str[i++] = (char)(buf[usIdx] | usMask);
519
32
    }
520
8
  }
521
4
  str[i] = '\0';
522
523
4
  proto_tree_add_string(tree, hf, tvb, offset, len, str);
524
525
4
  return len;
526
4
}
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
3
{
559
3
  if (bodylen >= 12) {
560
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_expansion_code,                   tvb, offset);
561
3
    offset += dissect_short(body_tree, hf_hartip_pt_rsp_expanded_device_type,             tvb, offset);
562
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_req_min_preambles,                tvb, offset);
563
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_hart_protocol_major_rev,          tvb, offset);
564
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_device_rev,                       tvb, offset);
565
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_software_rev,                     tvb, offset);
566
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_hardware_rev_physical_signal,     tvb, offset);
567
3
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_flage,                            tvb, offset);
568
3
    proto_tree_add_item(body_tree,     hf_hartip_pt_rsp_device_id,                        tvb, offset, 3, ENC_NA);
569
3
    offset += 3;
570
571
3
    if (bodylen >= 16) {
572
2
      offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_rsp_min_preambles,                tvb, offset);
573
2
      offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_max_device_variables,             tvb, offset);
574
2
      offset += dissect_short(body_tree, hf_hartip_pt_rsp_configuration_change_counter,     tvb, offset);
575
2
      offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_extended_device_status,           tvb, offset);
576
2
    }
577
578
3
    if (bodylen >= 18) {
579
2
      offset += dissect_short(body_tree, hf_hartip_pt_rsp_manufacturer_Identification_code, tvb, offset);
580
2
    }
581
582
3
    if (bodylen >= 22) {
583
2
      offset += dissect_short(body_tree, hf_hartip_pt_rsp_private_label,                    tvb, offset);
584
2
      /*offset += */dissect_byte(body_tree,  hf_hartip_pt_rsp_device_profile,                   tvb, offset);
585
2
    }
586
587
3
    return bodylen;
588
3
  }
589
590
0
  return 0;
591
3
}
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
2
{
620
2
  if (bodylen >= 24) {
621
2
    offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv_loop_current, tvb, offset);
622
2
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_pv_units,        tvb, offset);
623
2
    offset += dissect_float(body_tree, hf_hartip_pt_rsp_pv,              tvb, offset);
624
2
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_sv_units,        tvb, offset);
625
2
    offset += dissect_float(body_tree, hf_hartip_pt_rsp_sv,              tvb, offset);
626
2
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_tv_units,        tvb, offset);
627
2
    offset += dissect_float(body_tree, hf_hartip_pt_rsp_tv,              tvb, offset);
628
2
    offset += dissect_byte(body_tree,  hf_hartip_pt_rsp_qv_units,        tvb, offset);
629
2
    /*offset += */dissect_float(body_tree, hf_hartip_pt_rsp_qv,              tvb, offset);
630
631
2
    return bodylen;
632
2
  }
633
634
0
  return 0;
635
2
}
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, packet_info* pinfo, tvbuff_t *tvb, int offset, int bodylen)
740
2
{
741
2
  if (bodylen >= 21) {
742
2
    offset += dissect_packAscii(body_tree, pinfo, hf_hartip_pt_rsp_tag, tvb, offset, 6);
743
2
    offset += dissect_packAscii(body_tree, pinfo, hf_hartip_pt_rsp_packed_descriptor, tvb, offset, 12);
744
2
    offset += dissect_byte(body_tree,      hf_hartip_pt_rsp_day,                                 tvb, offset);
745
2
    offset += dissect_byte(body_tree,      hf_hartip_pt_rsp_month,                               tvb, offset);
746
2
    /*offset += */dissect_byte(body_tree,      hf_hartip_pt_rsp_year,                                tvb, offset);
747
748
2
    return bodylen;
749
2
  }
750
751
0
  return 0;
752
2
}
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
1
{
794
1
  if (bodylen >= 3) {
795
1
    proto_tree_add_item(body_tree, hf_hartip_pt_rsp_final_assembly_number, tvb, offset, 3, ENC_NA);
796
797
1
    return bodylen;
798
1
  }
799
800
0
  return 0;
801
1
}
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 off 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
     proto_tree_add_item_ret_uint8(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN, &byte_count);
914
0
     offset += 1;
915
0
     length -= 6;
916
917
0
     if ((byte_count >= 2) && (length >= 2) && (byte_count <= length)) {
918
0
       offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
919
0
       offset += dissect_byte(body_tree, hf_hartip_pt_device_status, tvb, offset);
920
0
       length -= 2;
921
0
       byte_count -= 2;
922
923
0
       if ((byte_count > 0) && (length > 0) && (byte_count <= length)) {
924
0
         proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
925
0
                             byte_count, ENC_NA);
926
0
       }
927
0
     }
928
929
0
    return bodylen;
930
0
  }
931
932
0
  return 0;
933
0
}
934
935
static int
936
dissect_cmd178(proto_tree *body_tree, tvbuff_t *tvb, int offset, int bodylen)
937
0
{
938
0
   uint16_t cmd;
939
0
   uint8_t number_of_cmds;
940
0
   uint8_t cmd_byte_count;
941
0
   int     length = bodylen;
942
0
   int     result;
943
944
0
   if (length >= 5) {
945
0
     number_of_cmds = tvb_get_uint8(tvb, offset);
946
0
     proto_tree_add_uint(body_tree, hf_hartip_pt_rsp_number_of_commands, tvb, offset, 1, number_of_cmds);
947
0
     offset += 1;
948
0
     length -= 1;
949
950
0
     for (unsigned i = 0; i < number_of_cmds; i++)
951
0
     {
952
0
       if (length >= 4)
953
0
       {
954
0
         cmd = tvb_get_ntohs(tvb, offset);
955
0
         proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
956
0
         offset += 2;
957
0
         length -= 2;
958
959
0
         cmd_byte_count = tvb_get_uint8(tvb, offset);
960
0
         proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_byte_count, tvb, offset, 1, ENC_BIG_ENDIAN);
961
0
         offset += 1;
962
0
         length -= 1;
963
964
0
         offset += dissect_byte(body_tree, hf_hartip_pt_response_code, tvb, offset);
965
0
         length -= 1;
966
0
         cmd_byte_count -= 1;
967
968
0
         if ((cmd_byte_count > 0) && (length > 0) && (cmd_byte_count <= length))
969
0
         {
970
0
           switch(cmd)
971
0
           {
972
0
             case 3:
973
0
               result = dissect_cmd3(body_tree, tvb, offset, cmd_byte_count);
974
0
               break;
975
0
             case 9:
976
0
               result = dissect_cmd9(body_tree, tvb, offset, cmd_byte_count);
977
0
               break;
978
0
             case 48:
979
0
               result = dissect_cmd48(body_tree, tvb, offset, cmd_byte_count);
980
0
               break;
981
0
             default:
982
0
               result = 0;
983
0
               break;
984
0
           }
985
986
0
           if (result == 0 ) {
987
0
             proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
988
0
                                 cmd_byte_count, ENC_NA);
989
0
           }
990
991
0
           offset += cmd_byte_count;
992
0
           length -= cmd_byte_count;
993
0
         }
994
0
       } else {
995
0
         return bodylen;
996
0
       }
997
0
     }
998
999
0
     return bodylen;
1000
0
   }
1001
1002
0
   return 0;
1003
0
}
1004
1005
static int
1006
dissect_cmd203(proto_tree *body_tree, tvbuff_t *tvb, int offset, int bodylen)
1007
0
{
1008
0
  if (bodylen >= 8) {
1009
0
    offset += dissect_short(body_tree, hf_hartip_pt_rsp_index_of_first_discrete_var, tvb, offset);
1010
0
    offset += dissect_byte(body_tree, hf_hartip_pt_rsp_number_of_discrete_vars,      tvb, offset);
1011
0
    offset += dissect_byte(body_tree, hf_hartip_pt_rsp_extended_device_status,       tvb, offset);
1012
0
    dissect_timestamp(body_tree, hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
1013
0
                      "TimeStamp for Most Recent Discrete Change", 4,                tvb, offset);
1014
0
    offset += 4;
1015
1016
0
    if (bodylen >= 11)
1017
0
    {
1018
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_state, tvb, offset);
1019
0
       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot0_discrete_var_status, tvb, offset);
1020
0
    }
1021
1022
0
    if (bodylen >= 14)
1023
0
    {
1024
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_state, tvb, offset);
1025
0
       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot1_discrete_var_status, tvb, offset);
1026
0
    }
1027
1028
0
    if (bodylen >= 17)
1029
0
    {
1030
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_state, tvb, offset);
1031
0
       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot2_discrete_var_status, tvb, offset);
1032
0
    }
1033
1034
0
    if (bodylen >= 20)
1035
0
    {
1036
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_state, tvb, offset);
1037
0
       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot3_discrete_var_status, tvb, offset);
1038
0
    }
1039
1040
0
    if (bodylen >= 23)
1041
0
    {
1042
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_state, tvb, offset);
1043
0
       offset += dissect_byte(body_tree, hf_hartip_pt_rsp_slot4_discrete_var_status, tvb, offset);
1044
0
    }
1045
1046
0
    if (bodylen >= 26)
1047
0
    {
1048
0
       offset += dissect_short(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_state, tvb, offset);
1049
0
       dissect_byte(body_tree, hf_hartip_pt_rsp_slot5_discrete_var_status,           tvb, offset);
1050
0
    }
1051
1052
0
    return bodylen;
1053
0
  }
1054
1055
0
  return 0;
1056
0
}
1057
1058
static int
1059
dissect_cmd31(proto_tree *body_tree, tvbuff_t *tvb, int offset, int bodylen)
1060
1
{
1061
1
  int     length = bodylen;
1062
1
  int     result = 0;
1063
1
  uint16_t cmd;
1064
1065
1
  if (length >= 2) {
1066
1
    cmd = tvb_get_ntohs(tvb, offset);
1067
1
    proto_tree_add_item(body_tree, hf_hartip_pt_rsp_command_number, tvb, offset, 2, ENC_BIG_ENDIAN);
1068
1
    offset += 2;
1069
1
    length -= 2;
1070
1071
1
    if (length > 0) {
1072
1
      switch(cmd)
1073
1
      {
1074
0
        case 64386:
1075
0
          result = dissect_cmd203(body_tree, tvb, offset, length);
1076
0
          break;
1077
1
      }
1078
1079
1
      if (result == 0) {
1080
1
        proto_tree_add_item(body_tree, hf_hartip_pt_rsp_data, tvb, offset,
1081
1
                            length, ENC_NA);
1082
1
      }
1083
1
    }
1084
1085
1
    return bodylen;
1086
1
  }
1087
1088
0
  return 0;
1089
1
}
1090
1091
static int
1092
dissect_parse_hart_cmds(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb, uint8_t cmd,
1093
                        int offset, int bodylen, int flags)
1094
10
{
1095
10
  switch(cmd)
1096
10
  {
1097
2
  case 0:
1098
2
  case 11:
1099
3
  case 21:
1100
3
    return dissect_cmd0(body_tree, tvb, offset, bodylen);
1101
0
  case 1:
1102
0
    return dissect_cmd1(body_tree, tvb, offset, bodylen);
1103
0
  case 2:
1104
0
    return dissect_cmd2(body_tree, tvb, offset, bodylen);
1105
2
  case 3:
1106
2
    return dissect_cmd3(body_tree, tvb, offset, bodylen);
1107
0
  case 6:
1108
0
  case 7:
1109
0
    return dissect_cmd7(body_tree, tvb, offset, bodylen);
1110
0
  case 8:
1111
0
    return dissect_cmd8(body_tree, tvb, offset, bodylen);
1112
0
  case 9:
1113
0
    return dissect_cmd9(body_tree, tvb, offset, bodylen);
1114
0
  case 12:
1115
0
  case 17:
1116
0
    if (bodylen >= 24)
1117
0
      return dissect_packAscii(body_tree, pinfo, hf_hartip_pt_rsp_message, tvb, offset, 24);
1118
0
    break;
1119
0
  case 13:
1120
2
  case 18:
1121
2
    return dissect_cmd13(body_tree, pinfo, tvb, offset, bodylen);
1122
0
  case 14:
1123
0
    return dissect_cmd14(body_tree, tvb, offset, bodylen);
1124
0
  case 15:
1125
0
    return dissect_cmd15(body_tree, tvb, offset, bodylen);
1126
1
  case 16:
1127
1
  case 19:
1128
1
    return dissect_cmd16(body_tree, tvb, offset, bodylen);
1129
0
  case 20:
1130
0
  case 22:
1131
0
    if (bodylen >= 32) {
1132
0
      proto_tree_add_item(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 32,
1133
0
                          ENC_ASCII|ENC_NA);
1134
0
      return 32;
1135
0
    }
1136
0
    break;
1137
1
  case 31:
1138
1
    return dissect_cmd31(body_tree, tvb, offset, bodylen);
1139
0
  case 33:
1140
0
    return dissect_cmd33(body_tree, tvb, offset, bodylen);
1141
0
  case 38:
1142
0
    return dissect_cmd38(body_tree, tvb, offset, bodylen);
1143
0
  case 48:
1144
0
    return dissect_cmd48(body_tree, tvb, offset, bodylen);
1145
0
  case 77:
1146
0
    return dissect_cmd77(body_tree, tvb, offset, bodylen, flags);
1147
0
  case 178:
1148
0
    return dissect_cmd178(body_tree, tvb, offset, bodylen);
1149
0
  case 203:
1150
0
    return dissect_cmd203(body_tree, tvb, offset, bodylen);
1151
10
  }
1152
1153
1
  return 0;
1154
10
}
1155
1156
static int
1157
dissect_pass_through(proto_tree *body_tree, packet_info* pinfo, tvbuff_t *tvb, int offset,
1158
                     int bodylen)
1159
13
{
1160
13
  uint8_t     delimiter;
1161
13
  uint8_t     cmd           = 0;
1162
13
  int         length        = bodylen;
1163
13
  int         is_short      = 0;
1164
13
  int         is_rsp        = 0;
1165
13
  int         num_preambles = 0;
1166
13
  int         result;
1167
13
  uint8_t     short_addr;
1168
13
  uint8_t     bytes         = 0;
1169
1170
  /* find number of preambles */
1171
22
  while (length > num_preambles) {
1172
22
    delimiter = tvb_get_uint8(tvb, offset + num_preambles);
1173
22
    if (delimiter != 0xFF)
1174
13
      break;
1175
1176
9
    num_preambles += 1;
1177
9
  }
1178
1179
13
  if (num_preambles > 0) {
1180
3
    proto_tree_add_item(body_tree, hf_hartip_pt_preambles, tvb, offset,
1181
3
                        num_preambles, ENC_NA);
1182
3
    offset += num_preambles;
1183
3
    length -= num_preambles;
1184
3
  }
1185
1186
13
  if (length > 0) {
1187
13
    delimiter = tvb_get_uint8(tvb, offset);
1188
1189
13
    static int * const hartip_pt_delimiter_flag[] = {
1190
13
        &hf_hartip_pt_delimiter_frame_type,
1191
13
        &hf_hartip_pt_delimiter_physical_layer_type,
1192
13
        &hf_hartip_pt_delimiter_number_of_expansion_bytes,
1193
13
        &hf_hartip_pt_delimiter_address_type,
1194
13
        NULL
1195
13
    };
1196
1197
13
    proto_tree_add_bitmask(body_tree, tvb, offset, hf_hartip_pt_delimiter, ett_hartip_pt_delimiter,
1198
13
                           hartip_pt_delimiter_flag, ENC_NA);
1199
13
    offset += 1;
1200
13
    length -= 1;
1201
1202
13
    if ((delimiter & 0x7) == 6) {
1203
3
      is_rsp = 1;
1204
10
    } else if ((delimiter & 0x7) == 1) {
1205
4
      is_rsp = 1;
1206
4
    }
1207
1208
13
    if ((delimiter & 0x80) == 0) {
1209
7
      is_short = 1;
1210
7
    }
1211
1212
13
    bytes = (delimiter & 0x60) >> 5;
1213
13
  }
1214
1215
13
  if (is_short == 1) {
1216
7
    if (length > 0) {
1217
7
      short_addr = tvb_get_uint8(tvb, offset);
1218
7
      short_addr = short_addr & 0x3F;
1219
7
      proto_tree_add_uint(body_tree, hf_hartip_pt_short_addr, tvb, offset, 1,
1220
7
                               short_addr);
1221
7
      offset += 1;
1222
7
      length -= 1;
1223
7
    }
1224
7
  } else {
1225
6
    if (length > 4) {
1226
6
      proto_tree_add_item(body_tree, hf_hartip_pt_long_addr, tvb, offset, 5, ENC_NA);
1227
6
      offset += 5;
1228
6
      length -= 5;
1229
6
    } else if (length > 0) {
1230
0
      proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, length, ENC_NA);
1231
0
      length = 0;
1232
0
    }
1233
6
  }
1234
1235
13
  if (bytes > 0) {
1236
6
    proto_tree_add_item(body_tree, hf_hartip_pt_expansion_bytes, tvb, offset, bytes, ENC_NA);
1237
6
    offset += bytes;
1238
6
    length -= bytes;
1239
6
  }
1240
1241
13
  if (length > 0) {
1242
12
    cmd = tvb_get_uint8(tvb, offset);
1243
12
    proto_tree_add_item(body_tree, hf_hartip_pt_command, tvb, offset, 1, ENC_BIG_ENDIAN);
1244
12
    offset += 1;
1245
12
    length -= 1;
1246
12
  }
1247
13
  if (length > 0) {
1248
12
    proto_tree_add_item(body_tree, hf_hartip_pt_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1249
12
    offset += 1;
1250
12
    length -= 1;
1251
12
  }
1252
1253
13
  if (is_rsp == 1) {
1254
7
    if (length > 0) {
1255
7
      proto_tree_add_item(body_tree, hf_hartip_pt_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1256
7
      offset += 1;
1257
7
      length -= 1;
1258
7
    }
1259
7
    if (length > 0) {
1260
7
      proto_tree_add_item(body_tree, hf_hartip_pt_device_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1261
7
      offset += 1;
1262
7
      length -= 1;
1263
7
    }
1264
7
  }
1265
1266
13
  if (length > 1) {
1267
10
    int flags = 0;
1268
10
    if ( is_rsp ) {
1269
5
      flags |= HARTIP_PT_IS_RSP;
1270
5
    }
1271
10
    result = dissect_parse_hart_cmds(body_tree, pinfo, tvb, cmd, offset, (length - 1), flags);
1272
10
    if (result == 0 ) {
1273
1
      proto_tree_add_item(body_tree, hf_hartip_pt_payload, tvb, offset,
1274
1
                          (length - 1), ENC_NA);
1275
1
    }
1276
10
    offset += (length - 1);
1277
10
    length = 1;
1278
10
  }
1279
13
  if (length > 0) {
1280
5
    proto_tree_add_checksum(body_tree, tvb, offset, hf_hartip_pt_checksum, -1, NULL, NULL, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1281
5
  }
1282
1283
13
  return bodylen;
1284
13
}
1285
1286
static void
1287
hartip_set_conversation(packet_info *pinfo)
1288
13
{
1289
13
  conversation_t *conversation = NULL;
1290
1291
13
  if (!pinfo->fd->visited && (pinfo->ptype == PT_UDP)) {
1292
    /*
1293
     * This function is called for a session initiate send over UDP.
1294
     * The session initiate is sent to the server on port HARTIP_PORT.
1295
     * The server then responds from a different port.  All subsequent
1296
     * communication for the session between the client and server
1297
     * uses the new server port and the original client port.
1298
     *
1299
     * A new conversation is created here and this dissector is set to
1300
     * be used for it.  This allows the packets to be dissected properly
1301
     * for this protocol.
1302
     */
1303
5
    conversation = find_conversation(pinfo->num,
1304
5
                                     &pinfo->src, &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
1305
5
                                     pinfo->srcport, 0, NO_PORT_B);
1306
5
    if( (conversation == NULL) ||
1307
4
        (conversation_get_dissector(conversation, pinfo->num) != hartip_udp_handle) ) {
1308
4
      conversation = conversation_new(pinfo->num,
1309
4
                                      &pinfo->src, &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
1310
4
                                      pinfo->srcport, 0, NO_PORT2);
1311
4
      conversation_set_dissector(conversation, hartip_udp_handle);
1312
4
    }
1313
5
  }
1314
13
}
1315
1316
static int
1317
dissect_hartip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1318
                      int offset)
1319
31
{
1320
31
  proto_tree      *hartip_tree, *hdr_tree, *body_tree;
1321
31
  proto_item      *hart_item;
1322
31
  int              bodylen;
1323
31
  uint8_t          message_type, message_id;
1324
31
  uint16_t         transaction_id, length;
1325
31
  const char      *msg_id_str, *msg_type_str;
1326
31
  hartip_tap_info *tapinfo;
1327
1328
31
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "HART_IP");
1329
31
  col_clear(pinfo->cinfo, COL_INFO);
1330
1331
31
  length  = tvb_get_ntohs(tvb, offset+6);
1332
1333
31
  hart_item = proto_tree_add_item(tree, proto_hartip, tvb, 0, length, ENC_NA);
1334
31
  hartip_tree = proto_item_add_subtree(hart_item, ett_hartip);
1335
1336
31
  hdr_tree = proto_tree_add_subtree(hartip_tree, tvb, offset, HARTIP_HEADER_LENGTH,
1337
31
                      ett_hartip_hdr, NULL, "HART_IP Header");
1338
1339
31
  proto_tree_add_item(hdr_tree, hf_hartip_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1340
31
  offset += 1;
1341
1342
31
  message_type = tvb_get_uint8(tvb, offset);
1343
31
  msg_type_str = val_to_str(pinfo->pool, message_type, hartip_message_type_values, "Unknown message type %d");
1344
31
  proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1345
31
  offset += 1;
1346
1347
31
  message_id = tvb_get_uint8(tvb, offset);
1348
31
  msg_id_str = val_to_str(pinfo->pool, message_id, hartip_message_id_values, "Unknown message %d");
1349
31
  proto_tree_add_item(hdr_tree, hf_hartip_hdr_message_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1350
31
  offset += 1;
1351
1352
  /* Setup statistics for tap. */
1353
31
  tapinfo = wmem_new(pinfo->pool, hartip_tap_info);
1354
31
  tapinfo->message_type = message_type;
1355
31
  tapinfo->message_id   = message_id;
1356
31
  tap_queue_packet(hartip_tap, pinfo, tapinfo);
1357
1358
31
  if (message_id == SESSION_INITIATE_ID) {
1359
13
    hartip_set_conversation(pinfo);
1360
13
  }
1361
1362
31
  proto_tree_add_item(hdr_tree, hf_hartip_hdr_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1363
31
  offset += 1;
1364
1365
31
  proto_tree_add_item_ret_uint16(hdr_tree, hf_hartip_hdr_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN, &transaction_id);
1366
31
  offset += 2;
1367
1368
31
  proto_item_append_text(hart_item, ", %s %s, Sequence Number %d", msg_id_str,
1369
31
                         msg_type_str, transaction_id);
1370
1371
31
  col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ",
1372
31
                      "%s %s, Sequence Number %d",
1373
31
                      msg_id_str, msg_type_str, transaction_id);
1374
31
  col_set_fence(pinfo->cinfo, COL_INFO);
1375
1376
31
  proto_tree_add_item(hdr_tree, hf_hartip_hdr_msg_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1377
31
  offset += 2;
1378
1379
31
  if (length < HARTIP_HEADER_LENGTH)
1380
0
    return tvb_reported_length(tvb);
1381
31
  bodylen = length - HARTIP_HEADER_LENGTH;
1382
1383
  /* add body elements. */
1384
31
  body_tree = proto_tree_add_subtree_format(hartip_tree, tvb, offset, bodylen,
1385
31
                           ett_hartip_body, NULL,
1386
31
                           "HART_IP Body, %s, %s", msg_id_str, msg_type_str);
1387
1388
31
  if ((message_type == ERROR_MSG_TYPE) ||
1389
27
      (message_type == NAK_MSG_TYPE)) {
1390
2
    offset += dissect_error(body_tree, tvb, offset, bodylen);
1391
29
  } else {
1392
    /*  Dissect the various HARTIP messages. */
1393
29
    switch(message_id) {
1394
11
    case SESSION_INITIATE_ID:
1395
11
      offset += dissect_session_init(body_tree, tvb, offset, bodylen);
1396
11
      break;
1397
0
    case SESSION_CLOSE_ID:
1398
0
      offset += dissect_session_close(body_tree, pinfo, tvb, offset, bodylen);
1399
0
      break;
1400
0
    case KEEP_ALIVE_ID:
1401
0
      offset += dissect_keep_alive(body_tree, pinfo, tvb, offset, bodylen);
1402
0
      break;
1403
13
    case PASS_THROUGH_ID:
1404
13
      offset += dissect_pass_through(body_tree, pinfo, tvb, offset, bodylen);
1405
13
      break;
1406
3
    default:
1407
3
      proto_tree_add_item(body_tree, hf_hartip_data, tvb, offset, bodylen, ENC_NA);
1408
3
      offset += bodylen;
1409
3
      break;
1410
29
    }
1411
29
  }
1412
1413
10
  return offset;
1414
31
}
1415
1416
static unsigned
1417
get_dissect_hartip_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1418
                       int offset, void *data _U_)
1419
14
{
1420
14
  return tvb_get_ntohs(tvb, offset+6);
1421
14
}
1422
1423
static int
1424
dissect_hartip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1425
13
{
1426
13
  return dissect_hartip_common(tvb, pinfo, tree, 0);
1427
13
}
1428
1429
static int
1430
dissect_hartip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1431
                   void *data)
1432
11
{
1433
  /* Simple heuristic check*/
1434
11
  const char * msg_str = try_val_to_str(tvb_get_uint8(tvb, 1), hartip_message_type_values);
1435
11
  if (!msg_str) {
1436
3
    return 0;
1437
3
  }
1438
1439
8
  msg_str = try_val_to_str(tvb_get_uint8(tvb, 2), hartip_message_id_values);
1440
8
  if (!msg_str) {
1441
1
    return 0;
1442
1
  }
1443
1444
7
  tcp_dissect_pdus(tvb, pinfo, tree, hartip_desegment, HARTIP_HEADER_LENGTH,
1445
7
                   get_dissect_hartip_len, dissect_hartip_pdu, data);
1446
7
  return tvb_reported_length(tvb);
1447
8
}
1448
1449
static int
1450
dissect_hartip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1451
                   void *data _U_)
1452
26
{
1453
26
  int offset = 0;
1454
1455
  /* Simple heuristic check*/
1456
26
  const char * msg_str = try_val_to_str(tvb_get_uint8(tvb, 1), hartip_message_type_values);
1457
26
  if (!msg_str) {
1458
5
    return 0;
1459
5
  }
1460
1461
21
  msg_str = try_val_to_str(tvb_get_uint8(tvb, 2), hartip_message_id_values);
1462
21
  if (!msg_str) {
1463
3
    return 0;
1464
3
  }
1465
1466
36
  while (tvb_reported_length_remaining(tvb, offset) >= HARTIP_HEADER_LENGTH)
1467
18
    offset += dissect_hartip_common(tvb, pinfo, tree, offset);
1468
1469
18
  return offset;
1470
21
}
1471
1472
void
1473
proto_register_hartip(void)
1474
16
{
1475
16
  static hf_register_info hf[] = {
1476
    /* HARTIP header elements. */
1477
16
    { &hf_hartip_hdr_version,
1478
16
      { "Version",           "hart_ip.version",
1479
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1480
16
        "HART_IP version number", HFILL }
1481
16
    },
1482
16
    { &hf_hartip_hdr_message_type,
1483
16
      { "Message Type",           "hart_ip.message_type",
1484
16
        FT_UINT8, BASE_DEC, VALS(hartip_message_type_values), 0,
1485
16
        "HART_IP message type", HFILL }
1486
16
    },
1487
16
    { &hf_hartip_hdr_message_id,
1488
16
      { "Message ID",           "hart_ip.message_id",
1489
16
        FT_UINT8, BASE_DEC, VALS(hartip_message_id_values), 0,
1490
16
        "HART_IP message id", HFILL }
1491
16
    },
1492
16
    { &hf_hartip_hdr_status,
1493
16
      { "Status",           "hart_ip.status",
1494
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1495
16
        "HART_IP status field", HFILL }
1496
16
    },
1497
16
    { &hf_hartip_hdr_transaction_id,
1498
16
      { "Sequence Number",           "hart_ip.transaction_id",
1499
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
1500
16
        "HART_IP Sequence Number", HFILL }
1501
16
    },
1502
16
    { &hf_hartip_hdr_msg_length,
1503
16
      { "Message Length",           "hart_ip.msg_length",
1504
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
1505
16
        "HART_IP Message Length", HFILL }
1506
16
    },
1507
1508
    /* HARTIP Body elements   */
1509
16
    { &hf_hartip_data,
1510
16
      { "Message Data",           "hart_ip.data",
1511
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1512
16
        "HART_IP Message Data", HFILL }
1513
16
    },
1514
16
    { &hf_hartip_master_type,
1515
16
      { "Host Type",           "hart_ip.session_init.master_type",
1516
16
        FT_UINT8, BASE_DEC, VALS(hartip_master_type_values), 0x0,
1517
16
        "Session Host Type", HFILL }
1518
16
    },
1519
16
    { &hf_hartip_inactivity_close_timer,
1520
16
      { "Inactivity Close Timer",           "hart_ip.session_init.inactivity_close_timer",
1521
16
        FT_UINT32, BASE_DEC, NULL, 0x0,
1522
16
        "Session Inactivity Close Timer", HFILL }
1523
16
    },
1524
16
    { &hf_hartip_error_code,
1525
16
      { "Error",           "hart_ip.error.error_code",
1526
16
        FT_UINT8, BASE_DEC, VALS(hartip_error_code_values), 0x0,
1527
16
        "Error Code", HFILL }
1528
16
    },
1529
1530
    /* HARTIP Pass-through commads. */
1531
16
    { &hf_hartip_pt_preambles,
1532
16
      { "Preambles",           "hart_ip.pt.preambles",
1533
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1534
16
        "Pass Through Preambles", HFILL }
1535
16
    },
1536
16
    { &hf_hartip_pt_delimiter,
1537
16
      { "Delimiter",           "hart_ip.pt.delimiter",
1538
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1539
16
        "Pass Through Delimiter", HFILL }
1540
16
    },
1541
16
    { &hf_hartip_pt_delimiter_frame_type,
1542
16
      { "Frame Type",           "hart_ip.pt.delimiter.frame_type",
1543
16
        FT_UINT8, BASE_DEC, VALS(hartip_pt_delimiter_frame_type_values), 0x07,
1544
16
        NULL, HFILL }
1545
16
    },
1546
16
    { &hf_hartip_pt_delimiter_physical_layer_type,
1547
16
      { "Physical Layer Type",           "hart_ip.pt.delimiter.physical_layer_type",
1548
16
        FT_UINT8, BASE_DEC, VALS(hartip_pt_delimiter_physical_layer_type_values), 0x18,
1549
16
        NULL, HFILL }
1550
16
    },
1551
16
    { &hf_hartip_pt_delimiter_number_of_expansion_bytes,
1552
16
      { "Number of Expansion Bytes",           "hart_ip.pt.delimiter.number_of_expansion_bytes",
1553
16
        FT_UINT8, BASE_DEC, NULL, 0x60,
1554
16
        NULL, HFILL }
1555
16
    },
1556
16
    { &hf_hartip_pt_delimiter_address_type,
1557
16
      { "Address Type",           "hart_ip.pt.delimiter.address_type",
1558
16
        FT_UINT8, BASE_DEC, VALS(hartip_pt_delimiter_address_type_values), 0x80,
1559
16
        NULL, HFILL }
1560
16
    },
1561
16
    { &hf_hartip_pt_short_addr,
1562
16
      { "Short Address",           "hart_ip.pt.short_addr",
1563
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1564
16
        "Pass Through Short Address", HFILL }
1565
16
    },
1566
16
    { &hf_hartip_pt_long_addr,
1567
16
      { "Long Address",           "hart_ip.pt.long_address",
1568
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1569
16
        "Pass Through Long Address", HFILL }
1570
16
    },
1571
16
        { &hf_hartip_pt_expansion_bytes,
1572
16
      { "Expansion Bytes",           "hart_ip.pt.expansion_bytes",
1573
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1574
16
        NULL, HFILL }
1575
16
    },
1576
16
    { &hf_hartip_pt_command,
1577
16
      { "Command",           "hart_ip.pt.command",
1578
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1579
16
        "Pass Through Command", HFILL }
1580
16
    },
1581
16
    { &hf_hartip_pt_length,
1582
16
      { "Length",           "hart_ip.pt.length",
1583
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1584
16
        "Pass Through Length", HFILL }
1585
16
    },
1586
16
    { &hf_hartip_pt_response_code,
1587
16
      { "Response Code",           "hart_ip.pt.response_code",
1588
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1589
16
        "Pass Through Response Code", HFILL }
1590
16
    },
1591
16
    { &hf_hartip_pt_device_status,
1592
16
      { "Device Status",           "hart_ip.pt.device_status",
1593
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1594
16
        "Pass Through Device Status", HFILL }
1595
16
    },
1596
16
    { &hf_hartip_pt_payload,
1597
16
      { "Payload",           "hart_ip.pt.payload",
1598
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1599
16
        "Pass Through Payload", HFILL }
1600
16
    },
1601
16
    { &hf_hartip_pt_checksum,
1602
16
      { "Checksum",           "hart_ip.pt.checksum",
1603
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1604
16
        "Pass Through Checksum", HFILL }
1605
16
    },
1606
1607
    /* add fields for universal commands. */
1608
    /* command 0 */
1609
16
    { &hf_hartip_pt_rsp_expansion_code,
1610
16
      { "Expansion Code",           "hart_ip.pt.rsp.expansion_code",
1611
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1612
16
        NULL, HFILL }
1613
16
    },
1614
16
    { &hf_hartip_pt_rsp_expanded_device_type,
1615
16
      { "Expanded Device Type",           "hart_ip.pt.rsp.expanded_device_type",
1616
16
        FT_UINT16, BASE_HEX, NULL, 0x0,
1617
16
        NULL, HFILL }
1618
16
    },
1619
16
    { &hf_hartip_pt_rsp_req_min_preambles,
1620
16
      { "Minimum Number of Request Preambles",           "hart_ip.pt.rsp.req_min_preambles",
1621
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1622
16
        NULL, HFILL }
1623
16
    },
1624
16
    { &hf_hartip_pt_rsp_hart_protocol_major_rev,
1625
16
      { "HART Universal Revision",           "hart_ip.pt.rsp.hart_univ_rev",
1626
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1627
16
        NULL, HFILL }
1628
16
    },
1629
16
    { &hf_hartip_pt_rsp_device_rev,
1630
16
      { "Device Revision",           "hart_ip.pt.rsp.device_rev",
1631
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1632
16
        NULL, HFILL }
1633
16
    },
1634
16
    { &hf_hartip_pt_rsp_software_rev,
1635
16
      { "Device Software Revision",           "hart_ip.pt.rsp.software_rev",
1636
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1637
16
        NULL, HFILL }
1638
16
    },
1639
16
    { &hf_hartip_pt_rsp_hardware_rev_physical_signal,
1640
16
      { "Hardware Rev and Physical Signaling",           "hart_ip.pt.rsp.hardrev_and_physical_signal",
1641
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1642
16
        NULL, HFILL }
1643
16
    },
1644
16
    { &hf_hartip_pt_rsp_flage,
1645
16
      { "Flags",           "hart_ip.pt.rsp.flags",
1646
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1647
16
        NULL, HFILL }
1648
16
    },
1649
16
    { &hf_hartip_pt_rsp_device_id,
1650
16
      { "Device ID",           "hart_ip.pt.rsp.device_id",
1651
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1652
16
        NULL, HFILL }
1653
16
    },
1654
16
    { &hf_hartip_pt_rsp_rsp_min_preambles,
1655
16
      { "Minimum Number of Response Preambles",           "hart_ip.pt.rsp.rsp_min_preambles",
1656
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1657
16
        NULL, HFILL }
1658
16
    },
1659
16
    { &hf_hartip_pt_rsp_max_device_variables,
1660
16
      { "Maximum Number of Device Variables",           "hart_ip.pt.rsp.device_variables",
1661
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1662
16
        NULL, HFILL }
1663
16
    },
1664
16
    { &hf_hartip_pt_rsp_configuration_change_counter,
1665
16
      { "Configuration Change Counter",           "hart_ip.pt.rsp.configure_change",
1666
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
1667
16
        NULL, HFILL }
1668
16
    },
1669
16
    { &hf_hartip_pt_rsp_extended_device_status,
1670
16
      { "Extended Device Status",           "hart_ip.pt.rsp.ext_device_status",
1671
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1672
16
        NULL, HFILL }
1673
16
    },
1674
16
    { &hf_hartip_pt_rsp_manufacturer_Identification_code,
1675
16
      { "Manufacturer ID",           "hart_ip.pt.rsp.manufacturer_Id",
1676
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
1677
16
        NULL, HFILL }
1678
16
    },
1679
16
    { &hf_hartip_pt_rsp_private_label,
1680
16
      { "Private Label",           "hart_ip.pt.rsp.private_label",
1681
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
1682
16
        NULL, HFILL }
1683
16
    },
1684
16
    { &hf_hartip_pt_rsp_device_profile,
1685
16
      { "Device Profile",           "hart_ip.pt.rsp.device_profile",
1686
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1687
16
        NULL, HFILL }
1688
16
    },
1689
1690
    /* command 2 */
1691
16
    { &hf_hartip_pt_rsp_pv_percent_range,
1692
16
      { "PV Percent Range",           "hart_ip.pt.rsp.pv_percent_range",
1693
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1694
16
        NULL, HFILL }
1695
16
    },
1696
1697
    /* command 3 */
1698
16
    { &hf_hartip_pt_rsp_pv_loop_current,
1699
16
      { "PV Loop Current",           "hart_ip.pt.rsp.pv_loop_current",
1700
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1701
16
        NULL, HFILL }
1702
16
    },
1703
16
    { &hf_hartip_pt_rsp_pv_units,
1704
16
      { "PV Units",           "hart_ip.pt.rsp.pv_units",
1705
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1706
16
        NULL, HFILL }
1707
16
    },
1708
16
    { &hf_hartip_pt_rsp_pv,
1709
16
      { "PV",           "hart_ip.pt.rsp.pv",
1710
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1711
16
        NULL, HFILL }
1712
16
    },
1713
16
    { &hf_hartip_pt_rsp_sv_units,
1714
16
      { "SV Units",           "hart_ip.pt.rsp.sv_units",
1715
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1716
16
        NULL, HFILL }
1717
16
    },
1718
16
    { &hf_hartip_pt_rsp_sv,
1719
16
      { "SV",           "hart_ip.pt.rsp.sv",
1720
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1721
16
        NULL, HFILL }
1722
16
    },
1723
16
    { &hf_hartip_pt_rsp_tv_units,
1724
16
      { "TV Units",           "hart_ip.pt.rsp.tv_units",
1725
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1726
16
        NULL, HFILL }
1727
16
    },
1728
16
    { &hf_hartip_pt_rsp_tv,
1729
16
      { "TV",           "hart_ip.pt.rsp.tv",
1730
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1731
16
        NULL, HFILL }
1732
16
    },
1733
16
    { &hf_hartip_pt_rsp_qv_units,
1734
16
      { "QV Units",           "hart_ip.pt.rsp.qv_units",
1735
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1736
16
        NULL, HFILL }
1737
16
    },
1738
16
    { &hf_hartip_pt_rsp_qv,
1739
16
      { "QV",           "hart_ip.pt.rsp.qv",
1740
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1741
16
        NULL, HFILL }
1742
16
    },
1743
1744
    /* command 7 */
1745
16
    { &hf_hartip_pt_rsp_loop_current_mode,
1746
16
      { "Loop Current Mode",                     "hart_ip.pt.rsp.loop_current_mode",
1747
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1748
16
        NULL, HFILL }
1749
16
    },
1750
1751
    /* command 8 */
1752
16
    { &hf_hartip_pt_rsp_primary_var_classify,
1753
16
      { "Primary Variable Classification",       "hart_ip.pt.rsp.primary_variable_classification",
1754
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1755
16
        NULL, HFILL }
1756
16
    },
1757
16
    { &hf_hartip_pt_rsp_secondary_var_classify,
1758
16
      { "Secondary Variable Classification",     "hart_ip.pt.rsp.secondary_variable_classification",
1759
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1760
16
        NULL, HFILL }
1761
16
    },
1762
16
    { &hf_hartip_pt_rsp_tertiary_var_classify,
1763
16
      { "Tertiary Variable Classification",      "hart_ip.pt.rsp.tertiary_variable_classification",
1764
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1765
16
        NULL, HFILL }
1766
16
    },
1767
16
    { &hf_hartip_pt_rsp_quaternary_var_classify,
1768
16
      { "Quaternary Variable Classification",    "hart_ip.pt.rsp.quaternary_variable_classification",
1769
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1770
16
        NULL, HFILL }
1771
16
    },
1772
1773
    /* command 9 */
1774
16
    { &hf_hartip_pt_rsp_slot0_device_var,
1775
16
      { "Slot0 Device Variable",           "hart_ip.pt.rsp.slot0_device_var",
1776
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1777
16
        NULL, HFILL }
1778
16
    },
1779
16
    { &hf_hartip_pt_rsp_slot0_device_var_classify,
1780
16
      { "Slot0 Device Variable Classification",  "hart_ip.pt.rsp.slot0_device_var_classification",
1781
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1782
16
        NULL, HFILL }
1783
16
    },
1784
16
    { &hf_hartip_pt_rsp_slot0_units,
1785
16
      { "Slot0 Units",           "hart_ip.pt.rsp.slot0_units",
1786
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1787
16
        NULL, HFILL }
1788
16
    },
1789
16
    { &hf_hartip_pt_rsp_slot0_device_var_value,
1790
16
      { "Slot0 Device Variable Value",           "hart_ip.pt.rsp.slot0_device_var_value",
1791
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1792
16
        NULL, HFILL }
1793
16
    },
1794
16
    { &hf_hartip_pt_rsp_slot0_device_var_status,
1795
16
      { "Slot0 Device Variable Status",           "hart_ip.pt.rsp.slot0_device_var_status",
1796
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1797
16
        NULL, HFILL }
1798
16
    },
1799
16
    { &hf_hartip_pt_rsp_slot1_device_var,
1800
16
      { "Slot1 Device Variable",           "hart_ip.pt.rsp.slot1_device_var",
1801
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1802
16
        NULL, HFILL }
1803
16
    },
1804
16
    { &hf_hartip_pt_rsp_slot1_device_var_classify,
1805
16
      { "Slot1 Device Variable Classification",           "hart_ip.pt.rsp.slot1_device_var_classify",
1806
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1807
16
        NULL, HFILL }
1808
16
    },
1809
16
    { &hf_hartip_pt_rsp_slot1_units,
1810
16
      { "Slot1 Units",           "hart_ip.pt.rsp.slot1_units",
1811
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1812
16
        NULL, HFILL }
1813
16
    },
1814
16
    { &hf_hartip_pt_rsp_slot1_device_var_value,
1815
16
      { "Slot1 Device Variable Value",           "hart_ip.pt.rsp.slot1_device_var_value",
1816
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1817
16
        NULL, HFILL }
1818
16
    },
1819
16
    { &hf_hartip_pt_rsp_slot1_device_var_status,
1820
16
      { "Slot1 Device Variable Status",           "hart_ip.pt.rsp.slot1_device_var_status",
1821
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1822
16
        NULL, HFILL }
1823
16
    },
1824
16
    { &hf_hartip_pt_rsp_slot2_device_var,
1825
16
      { "Slot2 Device Variable",           "hart_ip.pt.rsp.slot2_device_var",
1826
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1827
16
        NULL, HFILL }
1828
16
    },
1829
16
    { &hf_hartip_pt_rsp_slot2_device_var_classify,
1830
16
      { "Slot2 Device Variable Classification",           "hart_ip.pt.rsp.slot2_device_var_classify",
1831
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1832
16
        NULL, HFILL }
1833
16
    },
1834
16
    { &hf_hartip_pt_rsp_slot2_units,
1835
16
      { "Slot2 Units",           "hart_ip.pt.rsp.slot2_units",
1836
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1837
16
        NULL, HFILL }
1838
16
    },
1839
16
    { &hf_hartip_pt_rsp_slot2_device_var_value,
1840
16
      { "Slot2 Device Variable Value",           "hart_ip.pt.rsp.slot2_device_var_value",
1841
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1842
16
        NULL, HFILL }
1843
16
    },
1844
16
    { &hf_hartip_pt_rsp_slot2_device_var_status,
1845
16
      { "Slot2 Device Variable Status",           "hart_ip.pt.rsp.slot2_device_var_status",
1846
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1847
16
        NULL, HFILL }
1848
16
    },
1849
16
    { &hf_hartip_pt_rsp_slot3_device_var,
1850
16
      { "Slot3 Device Variable",           "hart_ip.pt.rsp.slot3_device_var",
1851
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1852
16
        NULL, HFILL }
1853
16
    },
1854
16
    { &hf_hartip_pt_rsp_slot3_device_var_classify,
1855
16
      { "Slot3 Device Variable Classification",           "hart_ip.pt.rsp.slot3_device_var_classify",
1856
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1857
16
        NULL, HFILL }
1858
16
    },
1859
16
    { &hf_hartip_pt_rsp_slot3_units,
1860
16
      { "Slot3 Units",           "hart_ip.pt.rsp.slot3_units",
1861
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1862
16
        NULL, HFILL }
1863
16
    },
1864
16
    { &hf_hartip_pt_rsp_slot3_device_var_value,
1865
16
      { "Slot3 Device Variable Value",           "hart_ip.pt.rsp.slot3_device_var_value",
1866
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1867
16
        NULL, HFILL }
1868
16
    },
1869
16
    { &hf_hartip_pt_rsp_slot3_device_var_status,
1870
16
      { "Slot3 Device Variable Status",           "hart_ip.pt.rsp.slot3_device_var_status",
1871
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1872
16
        NULL, HFILL }
1873
16
    },
1874
16
    { &hf_hartip_pt_rsp_slot4_device_var,
1875
16
      { "Slot4 Device Variable",           "hart_ip.pt.rsp.slot4_device_var",
1876
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1877
16
        NULL, HFILL }
1878
16
    },
1879
16
    { &hf_hartip_pt_rsp_slot4_device_var_classify,
1880
16
      { "Slot4 Device Variable Classification",           "hart_ip.pt.rsp.slot4_device_var_classify",
1881
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1882
16
        NULL, HFILL }
1883
16
    },
1884
16
    { &hf_hartip_pt_rsp_slot4_units,
1885
16
      { "Slot4 Units",           "hart_ip.pt.rsp.slot4_units",
1886
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1887
16
        NULL, HFILL }
1888
16
    },
1889
16
    { &hf_hartip_pt_rsp_slot4_device_var_value,
1890
16
      { "Slot4 Device Variable Value",           "hart_ip.pt.rsp.slot4_device_var_value",
1891
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1892
16
        NULL, HFILL }
1893
16
    },
1894
16
    { &hf_hartip_pt_rsp_slot4_device_var_status,
1895
16
      { "Slot4 Device Variable Status",           "hart_ip.pt.rsp.slot4_device_var_status",
1896
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1897
16
        NULL, HFILL }
1898
16
    },
1899
16
    { &hf_hartip_pt_rsp_slot5_device_var,
1900
16
      { "Slot5 Device Variable",           "hart_ip.pt.rsp.slot5_device_var",
1901
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1902
16
        NULL, HFILL }
1903
16
    },
1904
16
    { &hf_hartip_pt_rsp_slot5_device_var_classify,
1905
16
      { "Slot5 Device Variable Classification",           "hart_ip.pt.rsp.slot5_device_var_classify",
1906
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1907
16
        NULL, HFILL }
1908
16
    },
1909
16
    { &hf_hartip_pt_rsp_slot5_units,
1910
16
      { "Slot5 Units",           "hart_ip.pt.rsp.slot5_units",
1911
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1912
16
        NULL, HFILL }
1913
16
    },
1914
16
    { &hf_hartip_pt_rsp_slot5_device_var_value,
1915
16
      { "Slot5 Device Variable Value",           "hart_ip.pt.rsp.slot5_device_var_value",
1916
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1917
16
        NULL, HFILL }
1918
16
    },
1919
16
    { &hf_hartip_pt_rsp_slot5_device_var_status,
1920
16
      { "Slot5 Device Variable Status",           "hart_ip.pt.rsp.slot5_device_var_status",
1921
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1922
16
        NULL, HFILL }
1923
16
    },
1924
16
    { &hf_hartip_pt_rsp_slot6_device_var,
1925
16
      { "Slot6 Device Variable",           "hart_ip.pt.rsp.slot6_device_var",
1926
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1927
16
        NULL, HFILL }
1928
16
    },
1929
16
    { &hf_hartip_pt_rsp_slot6_device_var_classify,
1930
16
      { "Slot6 Device Variable Classification",           "hart_ip.pt.rsp.slot6_device_var_classify",
1931
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1932
16
        NULL, HFILL }
1933
16
    },
1934
16
    { &hf_hartip_pt_rsp_slot6_units,
1935
16
      { "Slot6 Units",           "hart_ip.pt.rsp.slot6_units",
1936
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1937
16
        NULL, HFILL }
1938
16
    },
1939
16
    { &hf_hartip_pt_rsp_slot6_device_var_value,
1940
16
      { "Slot6 Device Variable Value",           "hart_ip.pt.rsp.slot6_device_var_value",
1941
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1942
16
        NULL, HFILL }
1943
16
    },
1944
16
    { &hf_hartip_pt_rsp_slot6_device_var_status,
1945
16
      { "Slot6 Device Variable Status",           "hart_ip.pt.rsp.slot6_device_var_status",
1946
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1947
16
        NULL, HFILL }
1948
16
    },
1949
16
    { &hf_hartip_pt_rsp_slot7_device_var,
1950
16
      { "Slot7 Device Variable",           "hart_ip.pt.rsp.slot7_device_var",
1951
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1952
16
        NULL, HFILL }
1953
16
    },
1954
16
    { &hf_hartip_pt_rsp_slot7_device_var_classify,
1955
16
      { "Slot7 Device Variable Classification",           "hart_ip.pt.rsp.slot7_device_var_classify",
1956
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1957
16
        NULL, HFILL }
1958
16
    },
1959
16
    { &hf_hartip_pt_rsp_slot7_units,
1960
16
      { "Slot7 Units",           "hart_ip.pt.rsp.slot7_units",
1961
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1962
16
        NULL, HFILL }
1963
16
    },
1964
16
    { &hf_hartip_pt_rsp_slot7_device_var_value,
1965
16
      { "Slot7 Device Variable Value",           "hart_ip.pt.rsp.slot7_device_var_value",
1966
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
1967
16
        NULL, HFILL }
1968
16
    },
1969
16
    { &hf_hartip_pt_rsp_slot7_device_var_status,
1970
16
      { "Slot7 Device Variable Status",           "hart_ip.pt.rsp.slot7_device_var_status",
1971
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
1972
16
        NULL, HFILL }
1973
16
    },
1974
16
    { &hf_hartip_pt_rsp_slot0_timestamp,
1975
16
      { "Slot0 Data TimeStamp",           "hart_ip.pt.rsp.slot0_data_timestamp",
1976
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
1977
16
        NULL, HFILL }
1978
16
    },
1979
1980
    /* command 13 */
1981
16
    { &hf_hartip_pt_rsp_packed_descriptor,
1982
16
      { "Descriptor",           "hart_ip.pt.rsp.descriptor",
1983
16
        FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
1984
16
        NULL, HFILL }
1985
16
    },
1986
16
    { &hf_hartip_pt_rsp_day,
1987
16
      { "Day",           "hart_ip.pt.rsp.day",
1988
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1989
16
        NULL, HFILL }
1990
16
    },
1991
16
    { &hf_hartip_pt_rsp_month,
1992
16
      { "Month",           "hart_ip.pt.rsp.month",
1993
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1994
16
        NULL, HFILL }
1995
16
    },
1996
16
    { &hf_hartip_pt_rsp_year,
1997
16
      { "Year",           "hart_ip.pt.rsp.year",
1998
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
1999
16
        NULL, HFILL }
2000
16
    },
2001
2002
    /* command 14 */
2003
16
    { &hf_hartip_pt_rsp_transducer_serial_number,
2004
16
      { "Transducer Serial Number",              "hart_ip.pt.rsp.transducer_serial_number",
2005
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2006
16
        NULL, HFILL }
2007
16
    },
2008
16
    { &hf_hartip_pt_rsp_transducer_limit_min_span_units,
2009
16
      { "Transducer Limit Min Span Units",  "hart_ip.pt.rsp.transducer_limit_min_span_units",
2010
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2011
16
        NULL, HFILL }
2012
16
    },
2013
16
    { &hf_hartip_pt_rsp_upper_transducer_limit,
2014
16
      { "Upper Transducer Limit",                "hart_ip.pt.rsp.upper_transducer_limit",
2015
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2016
16
        NULL, HFILL }
2017
16
    },
2018
16
    { &hf_hartip_pt_rsp_lower_transducer_limit,
2019
16
      { "Lower Transducer Limit",                "hart_ip.pt.rsp.lower_transducer_limit",
2020
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2021
16
        NULL, HFILL }
2022
16
    },
2023
16
    { &hf_hartip_pt_rsp_minimum_span,
2024
16
      { "Minimum Span",                          "hart_ip.pt.rsp.minimum_span",
2025
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2026
16
        NULL, HFILL }
2027
16
    },
2028
2029
    /* command 15 */
2030
16
    { &hf_hartip_pt_rsp_pv_alarm_selection_code,
2031
16
      { "PV Alarm Selection Code",                     "hart_ip.pt.rsp.pv_alarm_selection_code",
2032
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2033
16
        NULL, HFILL }
2034
16
    },
2035
16
    { &hf_hartip_pt_rsp_pv_transfer_function_code,
2036
16
      { "PV Transfer Function Code",                   "hart_ip.pt.rsp.pv_transfer_function_code",
2037
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2038
16
        NULL, HFILL }
2039
16
    },
2040
16
    { &hf_hartip_pt_rsp_pv_upper_and_lower_range_values_units,
2041
16
      { "PV Upper and Lower Range Values Units",  "hart_ip.pt.rsp.pv_upper_and_lower_range_values_units",
2042
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2043
16
        NULL, HFILL }
2044
16
    },
2045
16
    { &hf_hartip_pt_rsp_pv_upper_range_value,
2046
16
      { "PV Upper Range Value",                        "hart_ip.pt.rsp.pv_upper_range_value",
2047
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2048
16
        NULL, HFILL }
2049
16
    },
2050
16
    { &hf_hartip_pt_rsp_pv_lower_range_value,
2051
16
      { "PV Lower Range Value",                        "hart_ip.pt.rsp.pv_lower_range_value",
2052
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2053
16
        NULL, HFILL }
2054
16
    },
2055
16
    { &hf_hartip_pt_rsp_pv_damping_value,
2056
16
      { "PV Damping Value",                            "hart_ip.pt.rsp.pv_damping_value",
2057
16
        FT_FLOAT, BASE_NONE, NULL, 0x0,
2058
16
        NULL, HFILL }
2059
16
    },
2060
16
    { &hf_hartip_pt_rsp_write_protect_code,
2061
16
      { "Write Protect Code",                          "hart_ip.pt.rsp.write_protect_code",
2062
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2063
16
        NULL, HFILL }
2064
16
    },
2065
16
    { &hf_hartip_pt_rsp_reserved,
2066
16
      { "Reserved",                                    "hart_ip.pt.rsp.reserved",
2067
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2068
16
        NULL, HFILL }
2069
16
    },
2070
16
    { &hf_hartip_pt_rsp_pv_analog_channel_flags,
2071
16
      { "PV Analog Channel Flags",                     "hart_ip.pt.rsp.pv_analog_channel_flags",
2072
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2073
16
        NULL, HFILL }
2074
16
    },
2075
2076
    /* command 16 and 19 */
2077
16
    { &hf_hartip_pt_rsp_final_assembly_number,
2078
16
      { "Final Assembly Number",                       "hart_ip.pt.rsp.final_assembly_number",
2079
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2080
16
        NULL, HFILL }
2081
16
    },
2082
2083
    /* Tag */
2084
16
    { &hf_hartip_pt_rsp_tag,
2085
16
      { "Tag",           "hart_ip.pt.rsp.tag",
2086
16
        FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2087
16
        NULL, HFILL }
2088
16
    },
2089
2090
    /* Message */
2091
16
    { &hf_hartip_pt_rsp_message,
2092
16
      { "Message",           "hart_ip.pt.rsp.message",
2093
16
        FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
2094
16
        NULL, HFILL }
2095
16
    },
2096
2097
    /* command 48 */
2098
16
    { &hf_hartip_pt_rsp_device_sp_status,
2099
16
      { "Device-Specific Status",           "hart_ip.pt.rsp.device_sp_status",
2100
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2101
16
        NULL, HFILL }
2102
16
    },
2103
16
    { &hf_hartip_pt_rsp_device_op_mode,
2104
16
      { "Device Operating Mode",           "hart_ip.pt.rsp.device_op_mode",
2105
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2106
16
        NULL, HFILL }
2107
16
    },
2108
16
    { &hf_hartip_pt_rsp_standardized_status_0,
2109
16
      { "Standardized Status 0",           "hart_ip.pt.rsp.standardized_status_0",
2110
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2111
16
        NULL, HFILL }
2112
16
    },
2113
16
    { &hf_hartip_pt_rsp_standardized_status_1,
2114
16
      { "Standardized Status 1",           "hart_ip.pt.rsp.standardized_status_1",
2115
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2116
16
        NULL, HFILL }
2117
16
    },
2118
16
    { &hf_hartip_pt_rsp_analog_channel_saturated,
2119
16
      { "Analog Channel Saturated",           "hart_ip.pt.rsp.analog_channel_saturated",
2120
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2121
16
        NULL, HFILL }
2122
16
    },
2123
16
    { &hf_hartip_pt_rsp_standardized_status_2,
2124
16
      { "Standardized Status 2",           "hart_ip.pt.rsp.standardized_status_2",
2125
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2126
16
        NULL, HFILL }
2127
16
    },
2128
16
    { &hf_hartip_pt_rsp_standardized_status_3,
2129
16
      { "Standardized Status 3",           "hart_ip.pt.rsp.standardized_status_3",
2130
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2131
16
        NULL, HFILL }
2132
16
    },
2133
16
    { &hf_hartip_pt_rsp_analog_channel_fixed,
2134
16
      { "Analog Channel Fixed",           "hart_ip.pt.rsp.analog_channel_fixed",
2135
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2136
16
        NULL, HFILL }
2137
16
    },
2138
2139
    /* command 77 */
2140
16
    { &hf_hartip_pt_rsp_io_card,
2141
16
      { "IO Card",                     "hart_ip.pt.rsp.io_card",
2142
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2143
16
        NULL, HFILL }
2144
16
    },
2145
16
    { &hf_hartip_pt_rsp_channel,
2146
16
      { "Channel",                     "hart_ip.pt.rsp.channel",
2147
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2148
16
        NULL, HFILL }
2149
16
    },
2150
16
    { &hf_hartip_pt_req_tx_preamble_count,
2151
16
      { "Transmit Preamble Count",     "hart_ip.pt.rsp.tx_preamble_count",
2152
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2153
16
        NULL, HFILL }
2154
16
    },
2155
16
    { &hf_hartip_pt_rsp_embedded_cmd_delimiter,
2156
16
      { "Embedded Command Delimiter",  "hart_ip.pt.rsp.embedded_command_delimiter",
2157
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2158
16
        NULL, HFILL }
2159
16
    },
2160
16
    { &hf_hartip_pt_rsp_poll_address,
2161
16
      { "Poll Address",                "hart_ip.pt.rsp.poll_address",
2162
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2163
16
        "Embedded Command Short Address", HFILL }
2164
16
    },
2165
16
    { &hf_hartip_pt_rsp_unique_id,
2166
16
      { "Unique ID",                   "hart_ip.pt.rsp.unique_id",
2167
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2168
16
        "Embedded Command Long Address", HFILL }
2169
16
    },
2170
16
    { &hf_hartip_pt_rsp_embedded_cmd,
2171
16
      { "Embedded Command",            "hart_ip.pt.rsp.embedded_command",
2172
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2173
16
        NULL, HFILL }
2174
16
    },
2175
2176
    /* command 178 */
2177
16
    { &hf_hartip_pt_rsp_number_of_commands,
2178
16
      { "Number of Commands",          "hart_ip.pt.rsp.number_of_commands",
2179
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2180
16
        NULL, HFILL }
2181
16
    },
2182
    /* command 31 and 178 */
2183
16
    { &hf_hartip_pt_rsp_command_number,
2184
16
      { "Command number",              "hart_ip.pt.rsp.command_number",
2185
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2186
16
        NULL, HFILL }
2187
16
    },
2188
16
    { &hf_hartip_pt_rsp_data,
2189
16
      { "Data",                        "hart_ip.pt.rsp.data",
2190
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2191
16
        NULL, HFILL }
2192
16
    },
2193
    /* command 77 and 178 */
2194
16
    { &hf_hartip_pt_rsp_command_byte_count,
2195
16
      { "Command byte count",          "hart_ip.pt.rsp.command_byte_count",
2196
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
2197
16
        NULL, HFILL }
2198
16
    },
2199
2200
    /* command 203 */
2201
16
    { &hf_hartip_pt_rsp_index_of_first_discrete_var,
2202
16
      { "Index of First Discrete Variable",           "hart_ip.pt.rsp.index_of_first_discrete_var",
2203
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2204
16
        NULL, HFILL }
2205
16
    },
2206
16
    { &hf_hartip_pt_rsp_number_of_discrete_vars,
2207
16
      { "Number of Discrete Variables",               "hart_ip.pt.rsp.number_of_discrete_vars",
2208
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2209
16
        NULL, HFILL }
2210
16
    },
2211
16
    { &hf_hartip_pt_rsp_timestamp_for_most_recent_discrete_change,
2212
16
      { "TimeStamp for Most Recent Discrete Change",  "hart_ip.pt.rsp.timestamp_for_most_recent_discrete_change",
2213
16
        FT_BYTES, BASE_NONE, NULL, 0x0,
2214
16
        NULL, HFILL }
2215
16
    },
2216
16
    { &hf_hartip_pt_rsp_slot0_discrete_var_state,
2217
16
      { "Slot0 Discrete Variable State",              "hart_ip.pt.rsp.slot0_discrete_var_state",
2218
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2219
16
        NULL, HFILL }
2220
16
    },
2221
16
    { &hf_hartip_pt_rsp_slot0_discrete_var_status,
2222
16
      { "Slot0 Discrete Variable Status",             "hart_ip.pt.rsp.slot0_discrete_var_status",
2223
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2224
16
        NULL, HFILL }
2225
16
    },
2226
16
    { &hf_hartip_pt_rsp_slot1_discrete_var_state,
2227
16
      { "Slot1 Discrete Variable State",              "hart_ip.pt.rsp.slot1_discrete_var_state",
2228
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2229
16
        NULL, HFILL }
2230
16
    },
2231
16
    { &hf_hartip_pt_rsp_slot1_discrete_var_status,
2232
16
      { "Slot1 Discrete Variable Status",             "hart_ip.pt.rsp.slot1_discrete_var_status",
2233
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2234
16
        NULL, HFILL }
2235
16
    },
2236
16
    { &hf_hartip_pt_rsp_slot2_discrete_var_state,
2237
16
      { "Slot2 Discrete Variable State",              "hart_ip.pt.rsp.slot2_discrete_var_state",
2238
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2239
16
        NULL, HFILL }
2240
16
    },
2241
16
    { &hf_hartip_pt_rsp_slot2_discrete_var_status,
2242
16
      { "Slot2 Discrete Variable Status",             "hart_ip.pt.rsp.slot2_discrete_var_status",
2243
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2244
16
        NULL, HFILL }
2245
16
    },
2246
16
    { &hf_hartip_pt_rsp_slot3_discrete_var_state,
2247
16
      { "Slot3 Discrete Variable State",              "hart_ip.pt.rsp.slot3_discrete_var_state",
2248
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2249
16
        NULL, HFILL }
2250
16
    },
2251
16
    { &hf_hartip_pt_rsp_slot3_discrete_var_status,
2252
16
      { "Slot3 Discrete Variable Status",             "hart_ip.pt.rsp.slot3_discrete_var_status",
2253
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2254
16
        NULL, HFILL }
2255
16
    },
2256
16
    { &hf_hartip_pt_rsp_slot4_discrete_var_state,
2257
16
      { "Slot4 Discrete Variable State",              "hart_ip.pt.rsp.slot4_discrete_var_state",
2258
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2259
16
        NULL, HFILL }
2260
16
    },
2261
16
    { &hf_hartip_pt_rsp_slot4_discrete_var_status,
2262
16
      { "Slot4 Discrete Variable Status",             "hart_ip.pt.rsp.slot4_discrete_var_status",
2263
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2264
16
        NULL, HFILL }
2265
16
    },
2266
16
    { &hf_hartip_pt_rsp_slot5_discrete_var_state,
2267
16
      { "Slot5 Discrete Variable State",              "hart_ip.pt.rsp.slot5_discrete_var_state",
2268
16
        FT_UINT16, BASE_DEC, NULL, 0x0,
2269
16
        NULL, HFILL }
2270
16
    },
2271
16
    { &hf_hartip_pt_rsp_slot5_discrete_var_status,
2272
16
      { "Slot5 Discrete Variable Status",             "hart_ip.pt.rsp.slot5_discrete_var_status",
2273
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
2274
16
        NULL, HFILL }
2275
16
    }
2276
16
  };
2277
2278
16
  static int *ett[] = {
2279
16
    &ett_hartip,
2280
16
    &ett_hartip_hdr,
2281
16
    &ett_hartip_body,
2282
16
    &ett_hartip_pt_delimiter
2283
16
  };
2284
2285
16
  static ei_register_info ei[] = {
2286
16
     { &ei_hartip_data_none, { "hart_ip.data.none", PI_PROTOCOL, PI_NOTE, "No data", EXPFILL }},
2287
16
     { &ei_hartip_data_unexpected, { "hart_ip.data.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected message body", EXPFILL }},
2288
16
  };
2289
2290
16
  module_t *hartip_module;
2291
16
  expert_module_t* expert_hartip;
2292
2293
16
  proto_hartip = proto_register_protocol("HART_IP Protocol", "HART_IP", "hart_ip");
2294
16
  proto_register_field_array(proto_hartip, hf, array_length(hf));
2295
16
  proto_register_subtree_array(ett, array_length(ett));
2296
16
  expert_hartip = expert_register_protocol(proto_hartip);
2297
16
  expert_register_field_array(expert_hartip, ei, array_length(ei));
2298
2299
16
  hartip_module = prefs_register_protocol(proto_hartip, NULL);
2300
16
  prefs_register_bool_preference(hartip_module, "desegment",
2301
16
                                  "Desegment all HART-IP messages spanning multiple TCP segments",
2302
16
                                  "Whether the HART-IP dissector should desegment all messages spanning multiple TCP segments",
2303
16
                                  &hartip_desegment);
2304
2305
16
  hartip_tap = register_tap("hart_ip");
2306
2307
16
  hartip_udp_handle = register_dissector_with_description("hart_ip", "HART-IP over UDP", dissect_hartip_udp, proto_hartip);
2308
16
  hartip_tcp_handle = register_dissector_with_description("hart_ip.tcp", "HART-IP over TCP", dissect_hartip_tcp, proto_hartip);
2309
16
}
2310
2311
void
2312
proto_reg_handoff_hartip(void)
2313
16
{
2314
16
  dissector_add_uint_with_preference("udp.port", HARTIP_PORT, hartip_udp_handle);
2315
16
  dissector_add_uint_with_preference("tcp.port", HARTIP_PORT, hartip_tcp_handle);
2316
2317
16
  stats_tree_register("hart_ip", "hart_ip", "HART-IP", 0,
2318
                      hartip_stats_tree_packet, hartip_stats_tree_init, NULL);
2319
16
}
2320
2321
/*
2322
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2323
 *
2324
 * Local variables:
2325
 * c-basic-offset: 2
2326
 * tab-width: 8
2327
 * indent-tabs-mode: nil
2328
 * End:
2329
 *
2330
 * vi: set shiftwidth=2 tabstop=8 expandtab:
2331
 * :indentSize=2:tabSize=8:noTabs=true:
2332
 */
2333