epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / plugins / epan / profinet / packet-pn-rtc-one.c
blob6bed963da85ff3e733b2aec0ed500b38d3ebf2fa
1 /* packet-pn-rtc-one.c
2 * Routines for PROFINET IO - RTC1 dissection.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1999 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
12 * The PN-IO protocol is a field bus protocol related to decentralized
13 * periphery and is developed by the PROFIBUS Nutzerorganisation e.V. (PNO),
14 * see: www.profibus.com
17 * PN-IO is based on the common DCE-RPC and the "lightweight" PN-RT
18 * (ethernet type 0x8892) protocols.
20 * The context manager (CM) part is handling context information
21 * (like establishing, ...) and is using DCE-RPC as its underlying
22 * protocol.
24 * The actual cyclic data transfer and acyclic notification uses the
25 * "lightweight" PN-RT protocol.
27 * There are some other related PROFINET protocols (e.g. PN-DCP, which is
28 * handling addressing topics).
30 * Please note: the PROFINET CBA protocol is independent of the PN-IO protocol!
34 * Cyclic PNIO RTC1 Data Dissection:
36 * To dissect cyclic PNIO RTC1 frames, this plug-in has to collect important module
37 * information out of "Ident OK", "Connect Request" and "Write Response"
38 * frames first.
40 * The data of Stationname-, -type and -id will be gained out of
41 * packet-pn-dcp.c. The header packet-pn.h will transfer those data between
42 * those two files.
44 * This file is used as a "addon" for packet-dcerpc-pn-io.c. Within "packet-dcerpc-pn-io.c"
45 * the defined structures in "packet-pn.h" will be filled with all necessary information.
46 * Those informations will be used in thise file to dissect cyclic PNIO RTC1 and PROFIsafe
47 * frames. Furthermore since RTC1 is a special frame type of PNIO, this dissection uses the
48 * already defined protocol PNIO.
50 * Overview for cyclic PNIO RTC1 data dissection functions:
51 * -> dissect_PNIO_C_SDU_RTC1 (general dissection of RTC1)
54 #include "config.h"
56 #include <stdio.h>
57 #include <string.h>
58 #include <glib.h>
59 #include <epan/packet.h>
60 #include <epan/dissectors/packet-dcerpc.h>
61 #include <epan/proto.h>
62 #include <epan/expert.h>
64 #include "packet-pn.h"
67 #define F_MESSAGE_TRAILER_4BYTE 4 /* PROFIsafe: Defines the Amount of Bytes for CRC and Status-/Controlbyte in PROFIsafe 2.4 */
68 #define F_MESSAGE_TRAILER_5BYTE 5 /* PROFIsafe: Defines the Amount of Bytes for CRC and Status-/Controlbyte in PROFIsafe 2.6 */
69 #define PN_INPUT_CR 1 /* PROFINET Input Connect Request value */
70 #define PN_INPUT_DATADESCRITPION 1 /* PROFINET Input Data Description value */
72 #define PA_PROFILE_API 0x9700u
74 static int proto_pn_io_rtc1;
76 /* General module information */
77 static int hf_pn_io_frame_info_type;
78 static int hf_pn_io_frame_info_vendor;
79 static int hf_pn_io_frame_info_nameofstation;
80 static int hf_pn_io_frame_info_gsd_found;
81 static int hf_pn_io_frame_info_gsd_error;
82 static int hf_pn_io_frame_info_gsd_path;
83 static int hf_pn_io_io_data_object;
84 static int hf_pn_io_io_data_object_info_module_diff;
85 static int hf_pn_io_io_data_object_info_moduleidentnumber;
86 static int hf_pn_io_io_data_object_info_submoduleidentnumber;
88 static int hf_pn_io_iocs;
89 static int hf_pn_io_iops;
90 static int hf_pn_io_ioxs_extension;
91 static int hf_pn_io_ioxs_res14;
92 static int hf_pn_io_ioxs_instance;
93 static int hf_pn_io_ioxs_datastate;
95 /* PROFIsafe statusbyte and controlbyte */
96 static int hf_pn_io_ps_sb;
97 static int hf_pn_io_ps_sb_iparOK;
98 static int hf_pn_io_ps_sb_DeviceFault;
99 static int hf_pn_io_ps_sb_CECRC;
100 static int hf_pn_io_ps_sb_WDtimeout;
101 static int hf_pn_io_ps_sb_FVactivated;
102 static int hf_pn_io_ps_sb_Toggle_d;
103 static int hf_pn_io_ps_sb_ConsNr_reset;
104 static int hf_pn_io_ps_sb_res;
105 static int hf_pn_io_ps_sb_toggelBitChanged;
106 static int hf_pn_io_ps_sb_toggelBitChange_slot_nr;
107 static int hf_pn_io_ps_sb_toggelBitChange_subslot_nr;
109 static int hf_pn_io_ps_cb;
110 static int hf_pn_io_ps_cb_iparEN;
111 static int hf_pn_io_ps_cb_OAReq;
112 static int hf_pn_io_ps_cb_resetConsNr;
113 static int hf_pn_io_ps_cb_useTO2;
114 static int hf_pn_io_ps_cb_activateFV;
115 static int hf_pn_io_ps_cb_Toggle_h;
116 static int hf_pn_io_ps_cb_Chf_ACK;
117 static int hf_pn_io_ps_cb_loopcheck;
118 static int hf_pn_io_ps_cb_toggelBitChanged;
119 static int hf_pn_io_ps_cb_toggelBitChange_slot_nr;
120 static int hf_pn_io_ps_cb_toggelBitChange_subslot_nr;
122 /* PROFIsafe */
123 static int hf_pn_io_ps_f_dest_adr;
124 static int hf_pn_io_ps_f_data;
126 /* PA Profile 4.02 */
127 static int hf_pn_pa_profile_status;
128 static int hf_pn_pa_profile_status_quality;
129 static int hf_pn_pa_profile_status_substatus_bad;
130 static int hf_pn_pa_profile_status_substatus_uncertain;
131 static int hf_pn_pa_profile_status_substatus_good;
132 static int hf_pn_pa_profile_status_update_event;
133 static int hf_pn_pa_profile_status_simulate;
134 static int hf_pn_pa_profile_value_8bit;
135 static int hf_pn_pa_profile_value_16bit;
136 static int hf_pn_pa_profile_value_float;
138 static int ett_pn_io_rtc;
139 static int ett_pn_io_ioxs;
140 static int ett_pn_io_io_data_object;
141 static int ett_pn_pa_profile_status;
143 static expert_field ei_pn_io_too_many_data_objects;
145 static const value_string pn_io_ioxs_extension[] = {
146 { 0x00 /* 0*/, "No IOxS octet follows" },
147 { 0x01 /* 1*/, "One more IOxS octet follows" },
148 { 0, NULL }
151 static const value_string pn_io_ioxs_instance[] = {
152 { 0x00 /* 0*/, "Detected by subslot" },
153 { 0x01 /* 1*/, "Detected by slot" },
154 { 0x02 /* 2*/, "Detected by IO device" },
155 { 0x03 /* 3*/, "Detected by IO controller" },
156 { 0, NULL }
159 static const value_string pn_io_ioxs_datastate[] = {
160 { 0x00 /* 0*/, "Bad" },
161 { 0x01 /* 1*/, "Good" },
162 { 0, NULL }
165 static const value_string pn_pa_profile_status_quality[] = {
166 { 0x00 /* 0*/, "BAD" },
167 { 0x01 /* 1*/, "UNCERTAIN" },
168 { 0x02 /* 2*/, "GOOD" },
169 { 0, NULL }
172 static const value_string pn_pa_profile_status_substatus_bad[] = {
173 { 0x0, "Non specific" },
174 { 0x2, "Not connected" },
175 { 0x8, "Passivated" },
176 { 0x9, "Maintenance alarm, more diagnosis" },
177 { 0xA, "Process related, no maintenance" },
178 { 0xF, "Function check, value not usable" },
179 { 0, NULL }
182 static const value_string pn_pa_profile_status_substatus_uncertain[] = {
183 { 0x2, "Substitute set" },
184 { 0x3, "Initial value" },
185 { 0xA, "Maintenance demanded" },
186 { 0xE, "Process related, no maintenance" },
187 { 0, NULL }
190 static const value_string pn_pa_profile_status_substatus_good[] = {
191 { 0x0, "Good" },
192 { 0x7, "Local override" },
193 { 0x8, "Initial fail safe" },
194 { 0x9, "Maintenance required" },
195 { 0xA, "Maintenance demanded" },
196 { 0xF, "Function check" },
197 { 0, NULL }
200 static const value_string pn_pa_profile_status_update_event[] = {
201 { 0x0, "No event" },
202 { 0x1, "Update event" },
203 { 0, NULL }
206 static const value_string pn_pa_profile_status_simulate[] = {
207 { 0x0, "Simulation off" },
208 { 0x1, "Simulation active" },
209 { 0, NULL }
213 static int * const ps_sb_fields[] = {
214 &hf_pn_io_ps_sb_res,
215 &hf_pn_io_ps_sb_ConsNr_reset,
216 &hf_pn_io_ps_sb_Toggle_d,
217 &hf_pn_io_ps_sb_FVactivated,
218 &hf_pn_io_ps_sb_WDtimeout,
219 &hf_pn_io_ps_sb_CECRC,
220 &hf_pn_io_ps_sb_DeviceFault,
221 &hf_pn_io_ps_sb_iparOK,
222 NULL
225 static int * const ps_cb_fields[] = {
226 &hf_pn_io_ps_cb_loopcheck,
227 &hf_pn_io_ps_cb_Chf_ACK,
228 &hf_pn_io_ps_cb_Toggle_h,
229 &hf_pn_io_ps_cb_activateFV,
230 &hf_pn_io_ps_cb_useTO2,
231 &hf_pn_io_ps_cb_resetConsNr,
232 &hf_pn_io_ps_cb_OAReq,
233 &hf_pn_io_ps_cb_iparEN,
234 NULL
237 static int * const ioxs_fields[] = {
238 &hf_pn_io_ioxs_datastate,
239 &hf_pn_io_ioxs_instance,
240 &hf_pn_io_ioxs_res14,
241 &hf_pn_io_ioxs_extension,
242 NULL
246 static int * const pa_profile_status_fields[] = {
247 &hf_pn_pa_profile_status_quality,
248 &hf_pn_pa_profile_status_substatus_bad,
249 &hf_pn_pa_profile_status_substatus_uncertain,
250 &hf_pn_pa_profile_status_substatus_good,
251 &hf_pn_pa_profile_status_update_event,
252 &hf_pn_pa_profile_status_simulate,
253 NULL
257 /* Dissector for PROFIsafe Status Byte */
258 static int
259 dissect_pn_io_ps_SB(tvbuff_t *tvb, int offset,
260 packet_info *pinfo _U_, proto_tree *tree, uint8_t *drep _U_, int hfindex, int * const *fields)
263 if (tree) {
264 uint8_t u8StatusByte;
265 proto_item *sb_item;
267 u8StatusByte = tvb_get_uint8(tvb, offset);
269 /* Add Status Byte subtree */
270 sb_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, ett_pn_io_ioxs, fields,
271 ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
272 proto_item_append_text(sb_item, " (%s)", ((u8StatusByte == 0x20) || (u8StatusByte == 0x00)) ? "normal" : "unnormal");
275 return offset + 1;
279 /* Dissector for PROFIsafe Control Byte */
280 static int
281 dissect_pn_io_ps_CB(tvbuff_t *tvb, int offset,
282 packet_info *pinfo _U_, proto_tree *tree, uint8_t *drep _U_, int hfindex, int * const *fields)
285 if (tree) {
286 uint8_t u8ControlByte;
287 proto_item *cb_item;
289 u8ControlByte = tvb_get_uint8(tvb, offset);
291 /* Add Status Byte subtree */
292 cb_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, ett_pn_io_ioxs, fields,
293 ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
294 proto_item_append_text(cb_item, " (%s)", ((u8ControlByte == 0x20) || (u8ControlByte == 0x00) ||
295 (u8ControlByte == 0xa0) || (u8ControlByte == 0x80)) ? "normal" : "unnormal");
298 return offset + 1;
302 /* Dissector for IOCS (As each IOCS stands for a specific Slot & Subslot) */
303 static int
304 dissect_PNIO_IOCS(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree,
305 uint8_t *drep _U_, int hfindex, uint16_t slotNr, uint16_t subSlotNr, int * const *fields)
308 if (tree) {
309 uint8_t u8IOxS;
310 proto_item *ioxs_item;
312 u8IOxS = tvb_get_uint8(tvb, offset);
314 /* Add ioxs subtree */
315 ioxs_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex,
316 ett_pn_io_ioxs, fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
317 proto_item_append_text(ioxs_item,
318 " (%s%s), Slot: 0x%x, Subslot: 0x%x",
319 (u8IOxS & 0x01) ? "another IOxS follows " : "",
320 (u8IOxS & 0x80) ? "good" : "bad",
321 slotNr,
322 subSlotNr);
325 return offset + 1;
329 /* dissect the IOxS (IOCS, IOPS) field */
330 static int
331 dissect_PNIO_IOxS(tvbuff_t *tvb, int offset,
332 packet_info *pinfo _U_, proto_tree *tree, uint8_t *drep _U_, int hfindex, int * const *fields)
335 if (tree) {
336 uint8_t u8IOxS;
337 proto_item *ioxs_item;
339 u8IOxS = tvb_get_uint8(tvb, offset);
341 /* Add ioxs subtree */
342 ioxs_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex,
343 ett_pn_io_ioxs, fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
344 proto_item_append_text(ioxs_item,
345 " (%s%s)",
346 (u8IOxS & 0x01) ? "another IOxS follows " : "",
347 (u8IOxS & 0x80) ? "good" : "bad");
350 return offset + 1;
354 /* Universal dissector for flexibel PROFIsafe Data 8 to 64 Bits */
355 static int
356 dissect_pn_io_ps_uint(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
357 proto_tree *tree, uint8_t *drep,
358 int hfindex, uint8_t bytelength, uint64_t *pdata)
360 uint64_t data;
361 bool generalDissection;
363 generalDissection = false;
365 switch (bytelength) {
366 case 1: /* 8 Bit Safety IO Data */
367 data = tvb_get_uint8(tvb, offset);
368 if (pdata)
369 *pdata = data;
370 break;
372 case 2: /* 16 Bit Safety IO Data */
373 data = tvb_get_letohs(tvb, offset);
374 if (pdata)
375 *pdata = data;
376 break;
378 case 3: /* 24 Bit Safety IO Data */
379 data = tvb_get_letoh24(tvb, offset);
380 if (pdata)
381 *pdata = data;
382 break;
384 case 4: /* 32 Bit Safety IO Data */
385 data = tvb_get_letohl(tvb, offset);
386 if (pdata)
387 *pdata = data;
388 break;
390 case 5: /* 40 Bit Safety IO Data */
391 data = tvb_get_letoh40(tvb, offset);
392 if (pdata)
393 *pdata = data;
394 break;
396 case 6: /* 48 Bit Safety IO Data */
397 data = tvb_get_letoh48(tvb, offset);
398 if (pdata)
399 *pdata = data;
400 break;
402 case 7: /* 56 Bit Safety IO Data */
403 data = tvb_get_letoh56(tvb, offset);
404 if (pdata)
405 *pdata = data;
406 break;
408 case 8: /* 64 Bit Safety IO Data */
409 data = tvb_get_letoh64(tvb, offset);
410 if (pdata)
411 *pdata = data;
412 break;
414 default: /* Safety IO Data is too big to save it into one variable */
415 dissect_pn_user_data(tvb, offset, pinfo, tree, bytelength, "Safety IO Data");
416 generalDissection = true;
417 break;
420 if (tree && generalDissection == false) {
421 proto_tree_add_item(tree, hfindex, tvb, offset, bytelength, DREP_ENC_INTEGER(drep));
424 return offset + bytelength;
428 /* dissect a PN-IO RTC1 Cyclic Service Data Unit */
430 dissect_PNIO_C_SDU_RTC1(tvbuff_t *tvb, int offset,
431 packet_info *pinfo, proto_tree *tree, uint8_t *drep _U_, uint16_t frameid)
433 proto_tree *data_tree = NULL;
435 /* Count & offset for comparison of the arrays */
436 uint16_t frameOffset;
437 uint32_t objectCounter;
438 bool inputFlag;
439 bool outputFlag;
440 bool psInfoText; /* Used to display only once per frame the info text "PROFIsafe Device" */
442 proto_item *data_item;
443 proto_item *IODataObject_item;
444 proto_item *IODataObject_item_info;
445 proto_tree *IODataObject_tree;
446 proto_item *ModuleID_item;
447 proto_item *ModuleDiff_item;
449 wmem_strbuf_t *moduleName;
451 uint8_t toggleBitSb;
452 uint8_t toggleBitCb;
453 uint64_t f_data;
455 uint8_t statusbyte;
456 uint8_t controlbyte;
457 uint8_t safety_io_data_length;
459 uint16_t number_io_data_objects_input_cr;
460 uint16_t number_iocs_input_cr;
461 uint16_t number_io_data_objects_output_cr;
462 uint16_t number_iocs_output_cr;
464 conversation_t *conversation;
465 stationInfo *station_info = NULL;
466 iocsObject *iocs_object;
467 ioDataObject *io_data_object;
468 moduleDiffInfo *module_diff_info;
469 wmem_list_frame_t *frame;
470 wmem_list_frame_t *frame_diff;
472 /* Initial */
473 frameOffset = 0;
474 f_data = 0;
475 inputFlag = false;
476 outputFlag = false;
477 psInfoText = false;
478 number_io_data_objects_input_cr = 0;
479 number_iocs_input_cr = 0;
480 number_io_data_objects_output_cr = 0;
481 number_iocs_output_cr = 0;
483 wmem_list_frame_t *aruuid_frame;
484 ARUUIDFrame *current_aruuid_frame = NULL;
485 uint32_t current_aruuid = 0;
487 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO"); /* set protocol name */
489 data_item = proto_tree_add_protocol_format(tree, proto_pn_io_rtc1, tvb, offset, tvb_captured_length(tvb),
490 "PROFINET IO Cyclic Service Data Unit: %u bytes", tvb_captured_length(tvb));
491 data_tree = proto_item_add_subtree(data_item, ett_pn_io_rtc);
493 /* dissect_dcerpc_uint16(tvb, offset, pinfo, data_tree, drep, hf_pn_io_packedframe_SFCRC, &u16SFCRC); */
494 if (dissect_CSF_SDU_heur(tvb, pinfo, data_tree, NULL))
495 return(tvb_captured_length(tvb));
497 /* Only dissect cyclic RTC1 frames, if PN Connect Request has been read */
498 conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0);
500 /* Detect input data package and output data package */
501 if (conversation != NULL) {
502 if (aruuid_frame_setup_list != NULL) {
503 for (aruuid_frame = wmem_list_tail(aruuid_frame_setup_list); aruuid_frame != NULL; aruuid_frame = wmem_list_frame_prev(aruuid_frame)) {
504 current_aruuid_frame = (ARUUIDFrame*)wmem_list_frame_data(aruuid_frame);
505 /* There are prerequisites to dissect RTC frame data */
506 /* Current station info must be found before RTC frame dissection starts */
507 /* if RTC frame has setup frame and setup frame number is less than RTC frame number AND if RTC frame has release frame and release frame number is greater than RTC frame number */
508 /* if RTC frame has setup frame and setup frame number is less than RTC frame number AND RTC frame does not have release frame yet! */
509 /* then, get AR UUID of current station info */
510 if ((current_aruuid_frame->setupframe && current_aruuid_frame->setupframe < pinfo->num) &&
511 ((current_aruuid_frame->releaseframe && current_aruuid_frame->releaseframe > pinfo->num) ||
512 !current_aruuid_frame->releaseframe)) {
513 if (current_aruuid_frame->inputframe == frameid) {
514 current_aruuid = current_aruuid_frame->aruuid.data1;
515 break;
517 else if (current_aruuid_frame->outputframe == frameid) {
518 current_aruuid = current_aruuid_frame->aruuid.data1;
519 break;
525 station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid);
527 if (station_info != NULL) {
528 pn_find_dcp_station_info(station_info, conversation);
530 if (pnio_ps_selection == true) {
531 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO_PS"); /* set PROFISsafe protocol name */
534 if (addresses_equal(&(pinfo->src), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->dst), conversation_key_addr2(conversation->key_ptr))) {
535 inputFlag = true;
536 outputFlag = false;
537 number_io_data_objects_input_cr = station_info->ioDataObjectNr_in;
538 number_iocs_input_cr = station_info->iocsNr_in;
541 if (addresses_equal(&(pinfo->dst), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->src), conversation_key_addr2(conversation->key_ptr))) {
542 outputFlag = true;
543 inputFlag = false;
544 number_io_data_objects_output_cr = station_info->ioDataObjectNr_out;
545 number_iocs_output_cr = station_info->iocsNr_out;
550 /* ------- Input (PNIO) / Response (PNIO_PS) Frame Handling ------- */
551 if (inputFlag) {
552 if (pnio_ps_selection == true) {
553 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb,
554 offset, 0, "Response", "Response Frame (IO_Device -> IO_Controller)");
556 else {
557 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb,
558 offset, 0, "Input", "Input Frame (IO_Device -> IO_Controller)");
561 if (station_info != NULL) {
562 if (station_info->typeofstation != NULL) {
563 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_vendor, tvb, 0,
564 0, station_info->typeofstation, "\"%s\"", station_info->typeofstation);
566 if (station_info->nameofstation != NULL) {
567 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_nameofstation, tvb, 0,
568 0, station_info->nameofstation, "\"%s\"", station_info->nameofstation);
571 if (station_info->gsdPathLength == true) { /* given path isn't too long for the array */
572 if (station_info->gsdFound == true) { /* found a GSD-file */
573 if (station_info->gsdLocation != NULL) {
574 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_found, tvb, offset, 0, ENC_NA);
575 proto_item_append_text(IODataObject_item_info, ": \"%s\"", station_info->gsdLocation);
578 else {
579 if (station_info->gsdLocation != NULL) {
580 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_error, tvb, offset, 0, ENC_NA);
581 proto_item_append_text(IODataObject_item_info, " Please place relevant GSD-file under \"%s\"", station_info->gsdLocation);
585 else {
586 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_path, tvb, offset, 0, ENC_NA);
587 proto_item_append_text(IODataObject_item_info, " Please check your GSD-file networkpath. (No Path configured)");
591 /* ---- Input IOData-/IOCS-Object Handling ---- */
592 objectCounter = number_io_data_objects_input_cr + number_iocs_input_cr;
593 if (objectCounter > (unsigned)tvb_reported_length_remaining(tvb, offset)) {
594 expert_add_info_format(pinfo, data_item, &ei_pn_io_too_many_data_objects, "Too many data objects: %d", objectCounter);
595 return(tvb_captured_length(tvb));
598 while (objectCounter--) {
599 /* ---- Input IO Data Object Handling ---- */
600 if (station_info != NULL) {
601 for (frame = wmem_list_head(station_info->ioobject_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) {
602 io_data_object = (ioDataObject*)wmem_list_frame_data(frame);
603 if (io_data_object->frameOffset == frameOffset) {
604 /* Found following object */
606 IODataObject_item = proto_tree_add_item(data_tree, hf_pn_io_io_data_object, tvb, offset, 0, ENC_NA);
607 IODataObject_tree = proto_item_add_subtree(IODataObject_item, ett_pn_io_io_data_object);
609 /* Control: the Device still uses the correct ModuleIdentNumber? */
610 for (frame_diff = wmem_list_head(station_info->diff_module); frame_diff != NULL; frame_diff = wmem_list_frame_next(frame_diff)) {
611 module_diff_info = (moduleDiffInfo*)wmem_list_frame_data(frame_diff);
612 if (io_data_object->moduleIdentNr != module_diff_info->modulID) {
613 ModuleDiff_item = proto_tree_add_item(IODataObject_tree, hf_pn_io_io_data_object_info_module_diff, tvb, 0, 0, ENC_NA);
614 proto_item_append_text(ModuleDiff_item, ": Device using ModuleIdentNumber 0x%08x instead of 0x%08x", module_diff_info->modulID, io_data_object->moduleIdentNr);
615 break;
619 proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_moduleidentnumber, tvb, 0, 0, io_data_object->moduleIdentNr);
620 proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_submoduleidentnumber, tvb, 0, 0, io_data_object->subModuleIdentNr);
622 /* PROFIsafe Supported Inputmodule handling */
623 if (io_data_object->profisafeSupported == true && pnio_ps_selection == true) {
624 if (io_data_object->profisafeSupported == true && psInfoText == false) {
625 /* Only add one information string per device to the infotext */
626 col_append_str(pinfo->cinfo, COL_INFO, ", PROFIsafe Device"); /* Add string to wireshark infotext */
627 psInfoText = true;
630 proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_f_dest_adr, tvb, 0, 0, io_data_object->f_dest_adr);
632 /* Get Safety IO Data */
633 if (io_data_object->f_crc_seed == false) {
634 safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_4BYTE;
635 } else {
636 safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_5BYTE;
639 if (safety_io_data_length > 0) {
640 offset = dissect_pn_io_ps_uint(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_f_data,
641 safety_io_data_length, &f_data);
644 /* ---- Check for new PNIO data using togglebit ---- */
645 statusbyte = tvb_get_uint8(tvb, offset);
646 toggleBitSb = statusbyte & 0x20; /* get ToggleBit of StatusByte */
648 if (io_data_object->lastToggleBit != toggleBitSb) { /* ToggleBit has changed --> new Data incoming */
649 /* Special Filter for ToggleBit within Statusbyte */
650 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChanged, tvb, offset, 0, toggleBitSb);
651 proto_item_set_hidden(ModuleID_item);
653 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChange_slot_nr, tvb, offset, 0, io_data_object->slotNr);
654 proto_item_set_hidden(ModuleID_item);
656 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChange_subslot_nr, tvb, offset, 0, io_data_object->subSlotNr);
657 proto_item_set_hidden(ModuleID_item);
660 offset = dissect_pn_io_ps_SB(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_sb, ps_sb_fields);
661 offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->f_crc_len, "CRC");
663 io_data_object->last_sb_cb = statusbyte; /* save the value of current statusbyte */
664 io_data_object->lastToggleBit = toggleBitSb; /* save the value of current togglebit within statusbyte */
665 } /* END of PROFIsafe Module Handling */
667 else {
668 /* Module is not PROFIsafe supported */
669 if (io_data_object->api == PA_PROFILE_API)
671 offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
673 else
675 offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
679 if (io_data_object->discardIOXS == false) {
680 offset = dissect_PNIO_IOxS(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_iops, ioxs_fields);
681 proto_item_set_len(IODataObject_item, io_data_object->length + 1); /* Length = Databytes + IOXS Byte */
683 else {
684 proto_item_set_len(IODataObject_item, io_data_object->length); /* Length = Databytes */
687 proto_item_append_text(IODataObject_item, ": Slot: 0x%x Subslot: 0x%x",
688 io_data_object->slotNr, io_data_object->subSlotNr);
691 /* ModuleIdentNr appears not only once in GSD-file -> set module name more generally */
692 if (io_data_object->amountInGSDML > 1) { /* if ModuleIdentNr only appears once in GSD-file, use the found GSD-file-ModuleName, else ... */
693 if (io_data_object->slotNr == 0) {
694 moduleName = wmem_strbuf_new(pinfo->pool, "Headstation");
696 else {
697 moduleName = wmem_strbuf_new(pinfo->pool, "Module");
700 if (io_data_object->profisafeSupported == true) {
701 /* PROFIsafe */
702 if (io_data_object->length >= 5) { /* 5 due to 3 CRC bytes & 1 status byte & (at least) 1 data byte */
703 wmem_strbuf_append(moduleName, ", DI");
705 else {
706 wmem_strbuf_append(moduleName, ", DO");
709 else {
710 /* PROFINET */
711 if (io_data_object->length > 0) {
712 wmem_strbuf_append(moduleName, ", DI");
714 else {
715 wmem_strbuf_append(moduleName, ", DO");
719 io_data_object->moduleNameStr = wmem_strdup(wmem_file_scope(), wmem_strbuf_get_str(moduleName));
722 proto_item_append_text(IODataObject_item, " ModuleName: \"%s\"", io_data_object->moduleNameStr);
724 /* emphasize the PROFIsafe supported Modul */
725 if (io_data_object->profisafeSupported == true && pnio_ps_selection == true) {
726 (proto_item_append_text(IODataObject_item, " (PROFIsafe Module)"));
730 /* Set frameOffset to its new value, to find the next object */
731 frameOffset = frameOffset + io_data_object->length; /* frameOffset = current value + data bytes */
732 if (io_data_object->discardIOXS == false) {
733 frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */
739 /* ---- Input IOCS Object Handling ---- */
740 if (station_info != NULL) {
741 for (frame = wmem_list_head(station_info->iocs_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) {
742 iocs_object = (iocsObject*)wmem_list_frame_data(frame);
743 if (iocs_object->frameOffset == frameOffset) {
744 offset = dissect_PNIO_IOCS(tvb, offset, pinfo, data_tree, drep, hf_pn_io_iocs, iocs_object->slotNr,
745 iocs_object->subSlotNr, ioxs_fields);
747 /* Set frameOffset to its new value, to find the next object */
748 frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */
750 break;
756 /* Dissect padding */
757 offset = dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), "GAP and RTCPadding");
758 } /* END of Input Frame Handling */
760 /* ----- Output (PNIO) / Request (PNIO_PS) Frame Handling ------ */
761 else if (outputFlag) {
762 if (pnio_ps_selection == true) {
763 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb,
764 offset, 0, "Request", "Request Frame (IO_Controller -> IO_Device)");
766 else {
767 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb,
768 offset, 0, "Output", "Output Frame (IO_Controller -> IO_Device)");
771 if (station_info != NULL) {
772 if (station_info->typeofstation != NULL) {
773 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_vendor, tvb, 0,
774 0, station_info->typeofstation, "\"%s\"", station_info->typeofstation);
776 if (station_info->nameofstation != NULL) {
777 proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_nameofstation, tvb, 0,
778 0, station_info->nameofstation, "\"%s\"", station_info->nameofstation);
781 if (station_info->gsdPathLength == true) { /* given path isn't too long for the array */
782 if (station_info->gsdFound == true) { /* found a GSD-file */
783 if (station_info->gsdLocation != NULL) {
784 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_found, tvb, offset, 0, ENC_NA);
785 proto_item_append_text(IODataObject_item_info, ": \"%s\"", station_info->gsdLocation);
788 else {
789 if (station_info->gsdLocation != NULL) {
790 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_error, tvb, offset, 0, ENC_NA);
791 proto_item_append_text(IODataObject_item_info, " Please place relevant GSD-file under \"%s\"", station_info->gsdLocation);
795 else {
796 IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_path, tvb, offset, 0, ENC_NA);
797 proto_item_append_text(IODataObject_item_info, " Please check your GSD-file networkpath. (No Path configured)");
801 /* ---- Output IOData-/IOCS-Object Handling ---- */
802 objectCounter = number_io_data_objects_output_cr + number_iocs_output_cr;
803 if (objectCounter > (unsigned)tvb_reported_length_remaining(tvb, offset)) {
804 expert_add_info_format(pinfo, data_item, &ei_pn_io_too_many_data_objects, "Too many data objects: %d", objectCounter);
805 return(tvb_captured_length(tvb));
807 while (objectCounter--) {
808 /* ---- Output IO Data Object Handling ---- */
809 if (station_info != NULL) {
810 for (frame = wmem_list_head(station_info->ioobject_data_out); frame != NULL; frame = wmem_list_frame_next(frame)) {
811 io_data_object = (ioDataObject*)wmem_list_frame_data(frame);
812 if (io_data_object != NULL && io_data_object->frameOffset == frameOffset) {
813 /* Found following object */
815 IODataObject_item = proto_tree_add_item(data_tree, hf_pn_io_io_data_object, tvb, offset, 0, ENC_NA);
816 IODataObject_tree = proto_item_add_subtree(IODataObject_item, ett_pn_io_io_data_object);
818 /* Control: the Device still uses the correct ModuleIdentNumber? */
819 for (frame_diff = wmem_list_head(station_info->diff_module); frame_diff != NULL; frame_diff = wmem_list_frame_next(frame_diff)) {
820 module_diff_info = (moduleDiffInfo*)wmem_list_frame_data(frame_diff);
821 if (io_data_object->moduleIdentNr != module_diff_info->modulID) {
822 ModuleDiff_item = proto_tree_add_item(IODataObject_tree, hf_pn_io_io_data_object_info_module_diff, tvb, 0, 0, ENC_NA);
823 proto_item_append_text(ModuleDiff_item, ": Device using ModuleIdentNumber 0x%08x instead of 0x%08x", module_diff_info->modulID, io_data_object->moduleIdentNr);
824 break;
828 proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_moduleidentnumber, tvb, 0, 0, io_data_object->moduleIdentNr);
829 proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_submoduleidentnumber, tvb, 0, 0, io_data_object->subModuleIdentNr);
831 if (io_data_object->profisafeSupported == true && pnio_ps_selection == true) {
832 if (io_data_object->profisafeSupported == true && psInfoText == false) {
833 /* Only add one information string per device to the infotext */
834 col_append_str(pinfo->cinfo, COL_INFO, ", PROFIsafe Device"); /* Add string to wireshark infotext */
835 psInfoText = true;
838 proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_f_dest_adr, tvb, 0, 0, io_data_object->f_dest_adr);
840 /* Get Safety IO Data */
841 if (io_data_object->f_crc_seed == false) {
842 safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_4BYTE;
843 } else {
844 safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_5BYTE;
847 if (safety_io_data_length > 0) {
848 offset = dissect_pn_io_ps_uint(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_f_data,
849 safety_io_data_length, &f_data);
852 /* ---- Check for new PNIO data using togglebit ---- */
853 controlbyte = tvb_get_uint8(tvb, offset);
854 toggleBitCb = controlbyte & 0x20; /* get ToggleBit of Controlbyte */
856 if (io_data_object->lastToggleBit != toggleBitCb) { /* ToggleBit has changed --> new Data incoming */
857 /* Special Filter for ToggleBit within Controlbyte */
858 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChanged, tvb, offset, 0, toggleBitCb);
859 proto_item_set_hidden(ModuleID_item);
861 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChange_slot_nr, tvb, offset, 0, io_data_object->slotNr);
862 proto_item_set_hidden(ModuleID_item);
864 ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChange_subslot_nr, tvb, offset, 0, io_data_object->subSlotNr);
865 proto_item_set_hidden(ModuleID_item);
868 offset = dissect_pn_io_ps_CB(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_cb, ps_cb_fields);
869 offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->f_crc_len, "CRC");
871 io_data_object->last_sb_cb = controlbyte; /* save the value of current controlbyte */
872 io_data_object->lastToggleBit = toggleBitCb; /* save the value of current togglebit within controlbyte */
873 } /* End of PROFIsafe Module Handling */
874 else {
875 /* Module is not PROFIsafe supported */
876 if (io_data_object->api == PA_PROFILE_API)
878 offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
880 else
882 offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
886 if (io_data_object->discardIOXS == false) {
887 offset = dissect_PNIO_IOxS(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_iops, ioxs_fields);
888 proto_item_set_len(IODataObject_item, io_data_object->length + 1); /* Length = Databytes + IOXS Byte */
890 else {
891 proto_item_set_len(IODataObject_item, io_data_object->length); /* Length = Databytes */
894 proto_item_append_text(IODataObject_item, ": Slot: 0x%x Subslot: 0x%x",
895 io_data_object->slotNr, io_data_object->subSlotNr);
898 /* ModuleIdentNr appears not only once in GSD-file -> set module name more generally */
899 if (io_data_object->amountInGSDML > 1) { /* if ModuleIdentNr only appears once in GSD-file, use the found GSD-file-ModuleName, else ... */
900 if (io_data_object->slotNr == 0) {
901 moduleName = wmem_strbuf_new(pinfo->pool, "Headstation");
903 else {
904 moduleName = wmem_strbuf_new(pinfo->pool, "Module");
907 if (io_data_object->profisafeSupported == true) {
908 /* PROFIsafe */
909 if (io_data_object->length >= 5) { /* 5 due to 3 CRC bytes & 1 status byte & (at least) 1 data byte */
910 wmem_strbuf_append(moduleName, ", DO");
912 else {
913 wmem_strbuf_append(moduleName, ", DI");
916 else {
917 /* PROFINET */
918 if (io_data_object->length > 0) {
919 wmem_strbuf_append(moduleName, ", DO");
921 else {
922 wmem_strbuf_append(moduleName, ", DI");
926 io_data_object->moduleNameStr = wmem_strdup(wmem_file_scope(), wmem_strbuf_get_str(moduleName));
929 proto_item_append_text(IODataObject_item, " ModuleName: \"%s\"", io_data_object->moduleNameStr);
931 /* emphasize the PROFIsafe supported Modul */
932 if (io_data_object->profisafeSupported == true && pnio_ps_selection == true) {
933 proto_item_append_text(IODataObject_item, " (PROFIsafe Module)");
936 /* Set frameOffset to its new value, to find the next object */
937 frameOffset = frameOffset + io_data_object->length; /* frameOffset = current value + data bytes */
938 if (io_data_object->discardIOXS == false) {
939 frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */
945 /* ---- Output IOCS Object Handling ---- */
946 if (station_info != NULL) {
947 for (frame = wmem_list_head(station_info->iocs_data_out); frame != NULL; frame = wmem_list_frame_next(frame)) {
948 iocs_object = (iocsObject*)wmem_list_frame_data(frame);
949 if (iocs_object->frameOffset == frameOffset) {
950 offset = dissect_PNIO_IOCS(tvb, offset, pinfo, data_tree, drep, hf_pn_io_iocs, iocs_object->slotNr,
951 iocs_object->subSlotNr, ioxs_fields);
953 /* Set frameOffset to its new value, to find the next object */
954 frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */
956 break;
962 /* Dissect padding */
963 offset = dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), "GAP and RTCPadding");
964 } /* END of Output Frame Handling */
966 return offset;
970 /* dissect the PA Profile status field */
971 static int
972 dissect_pn_pa_profile_status(tvbuff_t *tvb, int offset,
973 packet_info *pinfo _U_, proto_tree *tree, int hfindex)
976 if (tree) {
977 uint8_t u8status;
978 uint8_t quality;
979 proto_item *status_item;
980 proto_tree *status_tree;
981 const char* quality_name = NULL;
983 u8status = tvb_get_uint8(tvb, offset);
984 quality = (u8status >> 6u) & 0x3u;
986 /* add status subtree */
987 status_item = proto_tree_add_uint(tree, hfindex, tvb, offset, 1, u8status);
989 quality_name = try_val_to_str(quality, pn_pa_profile_status_quality);
991 proto_item_append_text(status_item,
992 " (%s)",
993 (quality_name != NULL) ? quality_name : "invalid");
995 status_tree = proto_item_add_subtree(status_item, ett_pn_pa_profile_status);
997 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_quality, tvb, offset, 1, ENC_NA);
999 switch(quality)
1001 case 0:
1002 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_bad, tvb, offset, 1, ENC_NA);
1003 break;
1004 case 1:
1005 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_uncertain, tvb, offset, 1, ENC_NA);
1006 break;
1007 case 2:
1008 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_good, tvb, offset, 1, ENC_NA);
1009 break;
1010 default:
1011 break;
1013 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_update_event, tvb, offset, 1, ENC_NA);
1014 proto_tree_add_item(status_tree, hf_pn_pa_profile_status_simulate, tvb, offset, 1, ENC_NA);
1017 return offset + 1;
1021 dissect_pn_pa_profile_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1022 proto_tree *tree, uint32_t length, const char *text)
1024 (void)text;
1026 All PA Profile submodules carry an 8-bit "status" plus the real data, which
1027 currently is a float, an 8-bit integer or a 16-bit integer.
1028 So we will have either 2, 3 or 5 bytes.
1030 if (length == 2u)
1032 proto_tree_add_item(tree, hf_pn_pa_profile_value_8bit, tvb, offset, 1, ENC_BIG_ENDIAN);
1033 dissect_pn_pa_profile_status(tvb, offset+1, pinfo, tree, hf_pn_pa_profile_status);
1035 else if (length == 3u)
1037 proto_tree_add_item(tree, hf_pn_pa_profile_value_16bit, tvb, offset, 2, ENC_BIG_ENDIAN);
1038 dissect_pn_pa_profile_status(tvb, offset+2, pinfo, tree, hf_pn_pa_profile_status);
1040 else if (length == 5u)
1042 proto_tree_add_item(tree, hf_pn_pa_profile_value_float, tvb, offset, 4, ENC_BIG_ENDIAN);
1043 dissect_pn_pa_profile_status(tvb, offset+4, pinfo, tree, hf_pn_pa_profile_status);
1045 else
1047 /* Delegate to standard user data if unknown */
1048 (void)dissect_pn_user_data(tvb, offset, pinfo, tree, length, "IO Data");
1051 return offset + length;
1054 void
1055 init_pn_io_rtc1(int proto)
1057 static hf_register_info hf[] = {
1058 { &hf_pn_io_io_data_object,
1059 { "IODataObject", "pn_io.io_data_object",
1060 FT_NONE, BASE_NONE, NULL, 0x0,
1061 NULL, HFILL }
1063 { &hf_pn_io_io_data_object_info_module_diff,
1064 { "Difference", "pn_io.io_data_object.diff_module",
1065 FT_NONE, BASE_NONE, NULL, 0x0,
1066 NULL, HFILL }
1068 { &hf_pn_io_io_data_object_info_moduleidentnumber,
1069 { "ModuleIdentNumber", "pn_io.io_data_object.module_nr",
1070 FT_UINT32, BASE_HEX, NULL, 0x0,
1071 NULL, HFILL }
1073 { &hf_pn_io_io_data_object_info_submoduleidentnumber,
1074 { "SubmoduleIdentNumber", "pn_io.io_data_object.submodule_nr",
1075 FT_UINT32, BASE_HEX, NULL, 0x0,
1076 NULL, HFILL }
1078 { &hf_pn_io_frame_info_type,
1079 { "PN Frame Type", "pn_io.frame_info.type",
1080 FT_STRING, BASE_NONE, NULL, 0x0,
1081 NULL, HFILL }
1083 { &hf_pn_io_frame_info_vendor,
1084 { "DeviceVendorValue", "pn_io.frame_info.vendor",
1085 FT_STRING, BASE_NONE, NULL, 0x0,
1086 NULL, HFILL }
1088 { &hf_pn_io_frame_info_nameofstation,
1089 { "NameOfStation", "pn_io.frame_info.nameofstation",
1090 FT_STRING, BASE_NONE, NULL, 0x0,
1091 NULL, HFILL }
1093 { &hf_pn_io_frame_info_gsd_found,
1094 { "GSD-file found", "pn_io.frame_info.gsd_found",
1095 FT_NONE, BASE_NONE, NULL, 0x0,
1096 NULL, HFILL }
1098 { &hf_pn_io_frame_info_gsd_error,
1099 { "GSD-file not found.", "pn_io.frame_info.gsd_error",
1100 FT_NONE, BASE_NONE, NULL, 0x0,
1101 NULL, HFILL }
1103 { &hf_pn_io_frame_info_gsd_path,
1104 { "GSD-file networkpath failure!", "pn_io.frame_info.gsd_path",
1105 FT_NONE, BASE_NONE, NULL, 0x0,
1106 NULL, HFILL }
1108 { &hf_pn_io_iocs,
1109 { "IOCS", "pn_io.ioxs",
1110 FT_UINT8, BASE_HEX, NULL, 0x0,
1111 NULL, HFILL }
1113 { &hf_pn_io_iops,
1114 { "IOPS", "pn_io.ioxs",
1115 FT_UINT8, BASE_HEX, NULL, 0x0,
1116 NULL, HFILL }
1118 { &hf_pn_io_ioxs_extension,
1119 { "Extension", "pn_io.ioxs.extension",
1120 FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_extension), 0x01,
1121 NULL, HFILL }
1123 { &hf_pn_io_ioxs_res14,
1124 { "Reserved", "pn_io.ioxs.res14",
1125 FT_UINT8, BASE_HEX, NULL, 0x1E,
1126 NULL, HFILL }
1128 { &hf_pn_io_ioxs_instance,
1129 { "Instance", "pn_io.ioxs.instance",
1130 FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_instance), 0x60,
1131 NULL, HFILL }
1133 { &hf_pn_io_ioxs_datastate,
1134 { "DataState", "pn_io.ioxs.datastate",
1135 FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_datastate), 0x80,
1136 NULL, HFILL }
1138 /* PROFIsafe parameter */
1139 /* Status Byte & Control Byte for PROFIsafe --- dissector handle */
1140 { &hf_pn_io_ps_sb,
1141 { "Status Byte", "pn_io.ps.sb",
1142 FT_UINT8, BASE_HEX, NULL, 0x0,
1143 NULL, HFILL }
1145 { &hf_pn_io_ps_sb_toggelBitChanged,
1146 { "Status Byte", "pn_io.ps.sb.toggle_d_changed",
1147 FT_UINT8, BASE_DEC, NULL, 0x0,
1148 NULL, HFILL }
1150 { &hf_pn_io_ps_sb_toggelBitChange_slot_nr,
1151 { "Slot_Number", "pn_io.ps.sb.toggle_d_changed.slot",
1152 FT_UINT16, BASE_DEC, NULL, 0x0,
1153 NULL, HFILL }
1155 { &hf_pn_io_ps_sb_toggelBitChange_subslot_nr,
1156 { "Sub_Slot_Number", "pn_io.ps.sb.toggle_d_changed.subslot",
1157 FT_UINT16, BASE_DEC, NULL, 0x0,
1158 NULL, HFILL }
1160 { &hf_pn_io_ps_cb,
1161 { "Control Byte", "pn_io.ps.cb",
1162 FT_UINT8, BASE_HEX, NULL, 0x0,
1163 NULL, HFILL }
1165 { &hf_pn_io_ps_cb_toggelBitChanged,
1166 { "Control Byte", "pn_io.ps.cb.toggle_h_changed",
1167 FT_UINT8, BASE_DEC, NULL, 0x0,
1168 NULL, HFILL }
1170 { &hf_pn_io_ps_cb_toggelBitChange_slot_nr,
1171 { "Slot_Number", "pn_io.ps.cb.toggle_h_changed.slot",
1172 FT_UINT16, BASE_DEC, NULL, 0x0,
1173 NULL, HFILL }
1175 { &hf_pn_io_ps_cb_toggelBitChange_subslot_nr,
1176 { "Sub_Slot_Number", "pn_io.ps.cb.toggle_h_changed.subslot",
1177 FT_UINT16, BASE_DEC, NULL, 0x0,
1178 NULL, HFILL }
1180 /* Structures for dissecting Status Byte & Control Byte PROFIsafe ---dissector details */
1181 { &hf_pn_io_ps_sb_iparOK,
1182 { "iPar_OK - F-Device has new iParameter values assigned", "pn_io.ps.sb.iPar_OK",
1183 FT_UINT8, BASE_HEX, NULL, 0x01,
1184 NULL, HFILL }
1186 { &hf_pn_io_ps_sb_DeviceFault,
1187 { "Device_Fault - Failure exists in F-Device or F-Module", "pn_io.ps.sb.DeviceFault",
1188 FT_UINT8, BASE_HEX, NULL, 0x02,
1189 NULL, HFILL }
1191 { &hf_pn_io_ps_sb_CECRC,
1192 { "CE_CRC - CRC Communication fault", "pn_io.ps.sb.CE_CRC",
1193 FT_UINT8, BASE_HEX, NULL, 0x04,
1194 NULL, HFILL }
1196 { &hf_pn_io_ps_sb_WDtimeout,
1197 { "WD_timeout - WatchDog timeout Communication fault", "pn_io.ps.sb.WD_timeout",
1198 FT_UINT8, BASE_HEX, NULL, 0x08,
1199 NULL, HFILL }
1201 { &hf_pn_io_ps_sb_FVactivated,
1202 { "FV_activated - Fail-safe values (FV) activated", "pn_io.ps.sb.FV_activated",
1203 FT_UINT8, BASE_HEX, NULL, 0x10,
1204 NULL, HFILL }
1206 { &hf_pn_io_ps_sb_Toggle_d,
1207 { "Toggle_d - Device-based Toggle Bit", "pn_io.ps.sb.Toggle_d",
1208 FT_UINT8, BASE_HEX, NULL, 0x20,
1209 NULL, HFILL }
1211 { &hf_pn_io_ps_sb_ConsNr_reset,
1212 { "cons_nr_R - F-Device has reset its consecutive number counter", "pn_io.ps.sb.cons_nr_R",
1213 FT_UINT8, BASE_HEX, NULL, 0x40,
1214 NULL, HFILL }
1216 { &hf_pn_io_ps_sb_res,
1217 { "Bit7 - reserved for future releases", "pn_io.ps.sb.bit7",
1218 FT_UINT8, BASE_HEX, NULL, 0x80,
1219 NULL, HFILL }
1221 { &hf_pn_io_ps_cb_iparEN,
1222 { "iPar_EN - iParameter assignment deblocked", "pn_io.ps.cb.iparEN",
1223 FT_UINT8, BASE_HEX, NULL, 0x01,
1224 NULL, HFILL }
1226 { &hf_pn_io_ps_cb_OAReq,
1227 { "OA_Req - Operator acknowledge requested", "pn_io.ps.cb.OA_Req",
1228 FT_UINT8, BASE_HEX, NULL, 0x02,
1229 NULL, HFILL }
1231 { &hf_pn_io_ps_cb_resetConsNr,
1232 { "R_cons_nr - Set the Virtual Consecutive Number within the F-Device to be \"0\"", "pn_io.ps.cb.R_cons_nr",
1233 FT_UINT8, BASE_HEX, NULL, 0x04,
1234 NULL, HFILL }
1236 { &hf_pn_io_ps_cb_useTO2,
1237 { "Bit3 - Reserved or Use the secondary watchdog (Use_TO2)", "pn_io.ps.cb.bit3",
1238 FT_UINT8, BASE_HEX, NULL, 0x08,
1239 NULL, HFILL }
1241 { &hf_pn_io_ps_cb_activateFV,
1242 { "activate_FV - Fail-safe values (FV) to be activated", "pn_io.ps.cb.activate_FV",
1243 FT_UINT8, BASE_HEX, NULL, 0x10,
1244 NULL, HFILL }
1246 { &hf_pn_io_ps_cb_Toggle_h,
1247 { "Toggle_h - Host-based Toggle Bit", "pn_io.ps.cb.Toggle_h",
1248 FT_UINT8, BASE_HEX, NULL, 0x20,
1249 NULL, HFILL }
1251 { &hf_pn_io_ps_cb_Chf_ACK,
1252 { "Bit6 - Reserved or Operator acknowledge after cleared channel fault (ChF_Ack)", "pn_io.ps.cb.bit6",
1253 FT_UINT8, BASE_HEX, NULL, 0x40,
1254 NULL, HFILL }
1256 { &hf_pn_io_ps_cb_loopcheck,
1257 { "Bit7 - Reserved or Loop-back check (Loopcheck, shall be set to 1)", "pn_io.ps.cb.bit7",
1258 FT_UINT8, BASE_HEX, NULL, 0x80,
1259 NULL, HFILL }
1261 /* PROFIsafe */
1262 { &hf_pn_io_ps_f_dest_adr,
1263 { "F_Dest_Add", "pn_io.ps.f_dest_add",
1264 FT_UINT16, BASE_DEC, NULL, 0x0,
1265 NULL, HFILL }
1267 { &hf_pn_io_ps_f_data,
1268 { "SafetyIO Data", "pn_io.ps.f_data",
1269 FT_UINT64, BASE_HEX, NULL, 0x0,
1270 NULL, HFILL }
1272 { &hf_pn_pa_profile_status,
1273 { "Status", "pn_io.pa.status",
1274 FT_UINT8, BASE_HEX, NULL, 0x0,
1275 NULL, HFILL }
1277 { &hf_pn_pa_profile_status_quality,
1278 { "Quality", "pn_io.pa.status.quality",
1279 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_quality), 0xC0,
1280 NULL, HFILL }
1282 { &hf_pn_pa_profile_status_substatus_bad,
1283 { "Substatus", "pn_io.pa.status.substatus",
1284 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_bad), 0x3C,
1285 NULL, HFILL }
1287 { &hf_pn_pa_profile_status_substatus_uncertain,
1288 { "Substatus", "pn_io.pa.status.substatus",
1289 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_uncertain), 0x3C,
1290 NULL, HFILL }
1292 { &hf_pn_pa_profile_status_substatus_good,
1293 { "Substatus", "pn_io.pa.status.substatus",
1294 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_good), 0x3C,
1295 NULL, HFILL }
1297 { &hf_pn_pa_profile_status_update_event,
1298 { "Update Event", "pn_io.pa.status.update",
1299 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_update_event), 0x02,
1300 NULL, HFILL }
1302 { &hf_pn_pa_profile_status_simulate,
1303 { "Simulate", "pn_io.pa.status.simulate",
1304 FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_simulate), 0x01,
1305 NULL, HFILL }
1307 { &hf_pn_pa_profile_value_8bit,
1308 { "Value", "pn_io.pa.value",
1309 FT_UINT8, BASE_HEX, NULL, 0x0,
1310 NULL, HFILL }
1312 { &hf_pn_pa_profile_value_16bit,
1313 { "Value", "pn_io.pa.value",
1314 FT_UINT16, BASE_HEX, NULL, 0x0,
1315 NULL, HFILL }
1317 { &hf_pn_pa_profile_value_float,
1318 { "Value", "pn_io.pa.value.float",
1319 FT_FLOAT, BASE_NONE, NULL, 0x0,
1320 NULL, HFILL }
1324 static int *ett[] = {
1325 &ett_pn_io_rtc,
1326 &ett_pn_io_ioxs,
1327 &ett_pn_io_io_data_object,
1328 &ett_pn_pa_profile_status
1331 static ei_register_info ei[] = {
1332 { &ei_pn_io_too_many_data_objects, { "pn_io.too_many_data_objects", PI_MALFORMED, PI_ERROR, "Too many data objects", EXPFILL }},
1335 expert_module_t* expert_pn_io;
1337 proto_pn_io_rtc1 = proto;
1338 proto_register_field_array(proto, hf, array_length(hf));
1339 proto_register_subtree_array(ett, array_length(ett));
1340 expert_pn_io = expert_register_protocol(proto_pn_io_rtc1);
1341 expert_register_field_array(expert_pn_io, ei, array_length(ei));
1346 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1348 * Local variables:
1349 * c-basic-offset: 4
1350 * tab-width: 8
1351 * indent-tabs-mode: nil
1352 * End:
1354 * vi: set shiftwidth=4 tabstop=8 expandtab:
1355 * :indentSize=4:tabSize=8:noTabs=true: