* Routines for CIP (Common Industrial Protocol) Motion dissection
* CIP Motion Home: www.odva.org
*
+ * This dissector includes items from:
+ * CIP Volume 9: CIP Motion, Edition 1.2
+ *
* Copyright 2006-2007
* Benjamin M. Stocks <bmstocks@ra.rockwell.com>
*
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <epan/packet.h>
+
+#include "packet-cipmotion.h"
+
#include "packet-cip.h"
+#include "packet-enip.h"
void proto_register_cipmotion(void);
-/* The entry point to the actual disection is: dissect_cipmotion */
+/* The entry point to the actual dissection is: dissect_cipmotion */
void proto_reg_handoff_cipmotion(void);
/* Protocol handle for CIP Motion */
static int proto_cipmotion = -1;
+static int proto_cipmotion3 = -1;
/* Header field identifiers, these are registered in the
* proto_register_cipmotion function along with the bites/bytes
static int hf_cip_data_tx_time_stamp = -1;
static int hf_cip_node_fltalarms = -1;
static int hf_cip_motor_cntrl = -1;
-static int hf_cip_fdbk_config = -1;
+static int hf_cip_feedback_mode = -1;
static int hf_cip_axis_control = -1;
static int hf_cip_control_status = -1;
+static int hf_cip_control_status_complete = -1;
+static int hf_cip_control_status_bus_up = -1;
+static int hf_cip_control_status_bus_unload = -1;
+static int hf_cip_control_status_power_loss = -1;
static int hf_cip_axis_response = -1;
static int hf_cip_axis_resp_stat = -1;
static int hf_cip_cmd_data_pos_cmd = -1;
static int hf_cip_cmd_data_vel_cmd = -1;
static int hf_cip_cmd_data_acc_cmd = -1;
static int hf_cip_cmd_data_trq_cmd = -1;
-static int hf_cip_cmd_data_pos_trim_cmd = -1;
-static int hf_cip_cmd_data_vel_trim_cmd = -1;
-static int hf_cip_cmd_data_acc_trim_cmd = -1;
-static int hf_cip_cmd_data_trq_trim_cmd = -1;
static int hf_cip_act_data_pos = -1;
static int hf_cip_act_data_vel = -1;
static int hf_cip_act_data_acc = -1;
-static int hf_cip_act_data_trq = -1;
-static int hf_cip_act_data_crnt = -1;
-static int hf_cip_act_data_vltg = -1;
-static int hf_cip_act_data_fqcy = -1;
static int hf_cip_sts_flt = -1;
static int hf_cip_sts_alrm = -1;
static int hf_cip_sts_sts = -1;
static int hf_cip_sts_iosts = -1;
static int hf_cip_sts_axis_safety = -1;
-static int hf_cip_sts_drive_safety = -1;
static int hf_cip_intrp = -1;
static int hf_cip_position_data_type = -1;
static int hf_cip_axis_state = -1;
static int hf_cip_axis_sts_alarm = -1;
static int hf_cip_axis_sts_dc_bus = -1;
static int hf_cip_axis_sts_pwr_struct = -1;
+static int hf_cip_axis_sts_flux_up = -1;
static int hf_cip_axis_sts_tracking = -1;
static int hf_cip_axis_sts_pos_lock = -1;
static int hf_cip_axis_sts_vel_lock = -1;
static int hf_cip_axis_sts_feedback_integ = -1;
static int hf_cip_axis_sts_shutdown = -1;
static int hf_cip_axis_sts_in_process = -1;
+static int hf_cip_axis_sts_dc_bus_unload = -1;
+static int hf_cip_axis_sts_ac_pwr_loss = -1;
+static int hf_cip_axis_sts_pos_cntrl_mode = -1;
+static int hf_cip_axis_sts_vel_cntrl_mode = -1;
+static int hf_cip_axis_sts_trq_cntrl_mode = -1;
static int hf_cip_cyclic_wrt_data = -1;
static int hf_cip_cyclic_rd_data = -1;
static int hf_cip_cyclic_write_blk = -1;
static int hf_cip_act_pos = -1;
static int hf_cip_act_vel = -1;
static int hf_cip_act_accel = -1;
-static int hf_cip_act_trq = -1;
-static int hf_cip_act_crnt = -1;
-static int hf_cip_act_volts = -1;
-static int hf_cip_act_freq = -1;
static int hf_cip_fault_type = -1;
static int hf_cip_fault_sub_code = -1;
static int hf_cip_fault_action = -1;
static int hf_cip_axis_safety_status = -1;
static int hf_cip_axis_safety_status_mfg = -1;
static int hf_cip_axis_safety_state = -1;
-static int hf_cip_drive_safety_status = -1;
static int hf_cip_cmd_data_set = -1;
static int hf_cip_act_data_set = -1;
static int hf_cip_sts_data_set = -1;
static int hf_var_devce_cyclic_rw_block_size = -1;
static int hf_var_devce_event_block_size = -1;
static int hf_var_devce_service_block_size = -1;
+static int hf_cip_data = -1;
/* Subtree pointers for the dissection */
static gint ett_cipmotion = -1;
static gint ett_cont_dev_header = -1;
+static gint ett_control_status = -1;
static gint ett_node_control = -1;
static gint ett_node_status = -1;
static gint ett_time_data_set = -1;
static gint ett_axis_status_set = -1;
static gint ett_command_control = -1;
+static dissector_handle_t cipmotion_handle;
+static dissector_handle_t cipmotion3_handle;
+
/* These are the BITMASKS for the Time Data Set header field */
#define TIME_DATA_SET_TIME_STAMP 0x1
#define TIME_DATA_SET_TIME_OFFSET 0x2
#define COMMAND_DATA_SET_VELOCITY 0x02
#define COMMAND_DATA_SET_ACCELERATION 0x04
#define COMMAND_DATA_SET_TORQUE 0x08
-#define COMMAND_DATA_SET_POSITION_TRIM 0x10
-#define COMMAND_DATA_SET_VELOCITY_TRIM 0x20
-#define COMMAND_DATA_SET_ACCELERATION_TRIM 0x40
-#define COMMAND_DATA_SET_TORQUE_TRIM 0x80
/* These are the BITMASKS for the Actual Data Set cyclic field */
#define ACTUAL_DATA_SET_POSITION 0x01
#define ACTUAL_DATA_SET_VELOCITY 0x02
#define ACTUAL_DATA_SET_ACCELERATION 0x04
-#define ACTUAL_DATA_SET_TORQUE 0x08
-#define ACTUAL_DATA_SET_CURRENT 0x10
-#define ACTUAL_DATA_SET_VOLTAGE 0x20
-#define ACTUAL_DATA_SET_FREQUENCY 0x40
/* These are the BITMASKS for the Status Data Set cyclic field */
#define STATUS_DATA_SET_AXIS_FAULT 0x01
#define STATUS_DATA_SET_AXIS_STATUS 0x04
#define STATUS_DATA_SET_AXIS_IO_STATUS 0x08
#define STATUS_DATA_SET_AXIS_SAFETY 0x10
-#define STATUS_DATA_SET_DRIVE_SAFETY 0x80
/* These are the BITMASKS for the Command Control cyclic field */
#define COMMAND_CONTROL_TARGET_UPDATE 0x03
#define FORMAT_VAR_CONTROL_TO_DEVICE 6
#define FORMAT_VAR_DEVICE_TO_CONTROL 7
+#define FEEDBACK_MODE_BITS 0x0F
+
/* Translate function to string - connection format values */
static const value_string cip_con_format_vals[] = {
{ FORMAT_FIXED_CONTROL_TO_DEVICE, "Fixed Controller-to-Device" },
{ 2, "Velocity Control" },
{ 3, "Acceleration Control" },
{ 4, "Torque Control" },
- { 5, "Current Control" },
{ 0, NULL }
};
-/* Translate function to string - feedback config values */
-static const value_string cip_fdbk_config_vals[] = {
+/* Translate function to string - feedback mode values */
+static const value_string cip_feedback_mode_vals[] = {
{ 0, "No Feedback" },
{ 1, "Master Feedback" },
{ 2, "Motor Feedback" },
{
{ 0, "No Request" },
{ 1, "Enable Request" },
- { 2, "Disble Request" },
+ { 2, "Disable Request" },
{ 3, "Shutdown Request" },
{ 4, "Shutdown Reset Request" },
{ 5, "Abort Request" },
{ 0, NULL }
};
-/* Translate function to string - control status values */
-static const value_string cip_control_status_vals[] =
-{
- { 1, "Configuration Complete" },
- { 0, NULL }
-};
-
/* Translate function to string - group sync Status */
static const value_string cip_sync_status_vals[] =
{
{ 4, "Shutdown Reset Acknowledge" },
{ 5, "Abort Acknowledge" },
{ 6, "Fault Reset Acknowledge" },
+ { 7, "Stop Process Acknowledge" },
+ { 8, "Change Actual Position Reference Acknowledge" },
+ { 9, "Change Command Position Reference Acknowledge" },
+ { 127, "Cancel Acknowledge" },
{ 0, NULL }
};
/* Translate function to string - axis state values */
static const value_string cip_axis_state_vals[] = {
{ 0, "Initializing" },
- { 1, "Pre-charging" },
+ { 1, "Pre-Charge" },
{ 2, "Stopped" },
{ 3, "Starting" },
{ 4, "Running" },
#define SC_RUN_INERTIA_TEST 0x51
#define SC_GET_INERTIA_TEST_DATA 0x52
#define SC_RUN_HOOKUP_TEST 0x53
-#define SC_GET_HOOKUP_TEST_DATA 0x53
+#define SC_GET_HOOKUP_TEST_DATA 0x54
/* Translate function to string - CIP Service codes */
static const value_string cip_sc_vals[] = {
{ SC_RUN_MOTOR_TEST, "Run Motor Test" },
{ SC_GET_MOTOR_TEST_DATA, "Get Motor Test Data" },
{ SC_RUN_INERTIA_TEST, "Run Inertia Test" },
- { SC_GET_INERTIA_TEST_DATA, "Get Intertia Test Data" },
+ { SC_GET_INERTIA_TEST_DATA, "Get Inertia Test Data" },
{ SC_RUN_HOOKUP_TEST, "Run Hookup Test" },
{ SC_GET_HOOKUP_TEST_DATA, "Get Hookup Test Data" },
{ 0, NULL }
};
+static int dissect_axis_status(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_axis_sts_local_ctrl,
+ &hf_cip_axis_sts_alarm,
+ &hf_cip_axis_sts_dc_bus,
+ &hf_cip_axis_sts_pwr_struct,
+ &hf_cip_axis_sts_flux_up,
+ &hf_cip_axis_sts_tracking,
+ &hf_cip_axis_sts_pos_lock,
+ &hf_cip_axis_sts_vel_lock,
+ &hf_cip_axis_sts_vel_standstill,
+ &hf_cip_axis_sts_vel_threshold,
+ &hf_cip_axis_sts_vel_limit,
+ &hf_cip_axis_sts_acc_limit,
+ &hf_cip_axis_sts_dec_limit,
+ &hf_cip_axis_sts_torque_threshold,
+ &hf_cip_axis_sts_torque_limit,
+ &hf_cip_axis_sts_cur_limit,
+ &hf_cip_axis_sts_therm_limit,
+ &hf_cip_axis_sts_feedback_integ,
+ &hf_cip_axis_sts_shutdown,
+ &hf_cip_axis_sts_in_process,
+ &hf_cip_axis_sts_dc_bus_unload,
+ &hf_cip_axis_sts_ac_pwr_loss,
+ &hf_cip_axis_sts_pos_cntrl_mode,
+ &hf_cip_axis_sts_vel_cntrl_mode,
+ &hf_cip_axis_sts_trq_cntrl_mode,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_axis_status, ett_axis_status_set, bits, ENC_LITTLE_ENDIAN);
+
+ return 4;
+}
+
+static int dissect_event_checking_control(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_evnt_ctrl_reg1_pos,
+ &hf_cip_evnt_ctrl_reg1_neg,
+ &hf_cip_evnt_ctrl_reg2_pos,
+ &hf_cip_evnt_ctrl_reg2_neg,
+ &hf_cip_evnt_ctrl_reg1_posrearm,
+ &hf_cip_evnt_ctrl_reg1_negrearm,
+ &hf_cip_evnt_ctrl_reg2_posrearm,
+ &hf_cip_evnt_ctrl_reg2_negrearm,
+ &hf_cip_evnt_ctrl_marker_pos,
+ &hf_cip_evnt_ctrl_marker_neg,
+ &hf_cip_evnt_ctrl_home_pos,
+ &hf_cip_evnt_ctrl_home_neg,
+ &hf_cip_evnt_ctrl_home_pp,
+ &hf_cip_evnt_ctrl_home_pm,
+ &hf_cip_evnt_ctrl_home_mp,
+ &hf_cip_evnt_ctrl_home_mm,
+ &hf_cip_evnt_ctrl_acks,
+ // The dissector will indicate if the protocol is requesting an extended event format but will not dissect it.
+ &hf_cip_evnt_extend_format,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_event_checking, ett_event_check_ctrl, bits, ENC_LITTLE_ENDIAN);
+
+ return 4;
+}
+
+static int dissect_event_checking_status(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_evnt_sts_reg1_pos,
+ &hf_cip_evnt_sts_reg1_neg,
+ &hf_cip_evnt_sts_reg2_pos,
+ &hf_cip_evnt_sts_reg2_neg,
+ &hf_cip_evnt_sts_reg1_posrearm,
+ &hf_cip_evnt_sts_reg1_negrearm,
+ &hf_cip_evnt_sts_reg2_posrearm,
+ &hf_cip_evnt_sts_reg2_negrearm,
+ &hf_cip_evnt_sts_marker_pos,
+ &hf_cip_evnt_sts_marker_neg,
+ &hf_cip_evnt_sts_home_pos,
+ &hf_cip_evnt_sts_home_neg,
+ &hf_cip_evnt_sts_home_pp,
+ &hf_cip_evnt_sts_home_pm,
+ &hf_cip_evnt_sts_home_mp,
+ &hf_cip_evnt_sts_home_mm,
+ &hf_cip_evnt_sts_nfs,
+ // The dissector will indicate if the protocol is requesting an extended event format but will not dissect it.
+ &hf_cip_evnt_extend_format,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_event_status, ett_event_check_sts, bits, ENC_LITTLE_ENDIAN);
+
+ return 4;
+}
+
+static int dissect_actual_data_set_bits(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_act_data_pos,
+ &hf_cip_act_data_vel,
+ &hf_cip_act_data_acc,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_act_data_set, ett_actual_data_set, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+static int dissect_command_data_set_bits(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_cmd_data_pos_cmd,
+ &hf_cip_cmd_data_vel_cmd,
+ &hf_cip_cmd_data_acc_cmd,
+ &hf_cip_cmd_data_trq_cmd,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_cmd_data_set, ett_command_data_set, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+static int dissect_command_control(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_intrp,
+ &hf_cip_position_data_type,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_command_control, ett_command_control, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+
+static int dissect_node_control(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_node_control_remote,
+ &hf_cip_node_control_sync,
+ &hf_cip_node_data_valid,
+ &hf_cip_node_fault_reset,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_node_control, ett_node_control, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+static int dissect_node_status(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_node_control_remote,
+ &hf_cip_node_control_sync,
+ &hf_cip_node_data_valid,
+ &hf_cip_node_device_faulted,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_node_status, ett_node_status, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+static int dissect_control_status(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
+ int offset, int total_len _U_)
+{
+ static const int* bits[] = {
+ &hf_cip_control_status_complete,
+ &hf_cip_control_status_bus_up,
+ &hf_cip_control_status_bus_unload,
+ &hf_cip_control_status_power_loss,
+ NULL
+ };
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_cip_control_status, ett_control_status, bits, ENC_LITTLE_ENDIAN);
+
+ return 1;
+}
+
+attribute_info_t cip_motion_attribute_vals[] = {
+ { CI_CLS_MOTION, CIP_ATTR_CLASS, 14, -1, "Node Control", cip_dissector_func, NULL, dissect_node_control },
+ { CI_CLS_MOTION, CIP_ATTR_CLASS, 15, -1, "Node Status", cip_dissector_func, NULL, dissect_node_status },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 40, -1, "Control Mode", cip_usint, &hf_cip_motor_cntrl, NULL },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 60, -1, "Event Checking Control", cip_dissector_func, NULL, dissect_event_checking_control },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 61, -1, "Event Checking Status", cip_dissector_func, NULL, dissect_event_checking_status },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 89, -1, "Control Status", cip_dissector_func, NULL, dissect_control_status },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 90, -1, "Actual Data Set", cip_dissector_func, NULL, dissect_actual_data_set_bits },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 91, -1, "Command Data Set", cip_dissector_func, NULL, dissect_command_data_set_bits },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 92, -1, "Command Control", cip_dissector_func, NULL, dissect_command_control },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 431, -1, "Position Trim", cip_dint, &hf_cip_pos_trim, NULL },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 451, -1, "Velocity Trim", cip_real, &hf_cip_vel_trim, NULL },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 481, -1, "Acceleration Trim", cip_real, &hf_cip_accel_trim, NULL },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 491, -1, "Torque Trim", cip_real, &hf_cip_trq_trim, NULL },
+ { CI_CLS_MOTION, CIP_ATTR_INSTANCE, 651, -1, "Axis Status", cip_dissector_func, NULL, dissect_axis_status },
+};
+
/*
* Function name: dissect_cmd_data_set
*
bytes_used += 4;
}
- if ( (cmd_data_set & COMMAND_DATA_SET_POSITION_TRIM) == COMMAND_DATA_SET_POSITION_TRIM )
- {
- /* Display the command data set position trim value */
- proto_tree_add_item(tree, hf_cip_pos_trim, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
- if ( (cmd_data_set & COMMAND_DATA_SET_VELOCITY_TRIM) == COMMAND_DATA_SET_VELOCITY_TRIM )
- {
- /* Display the command data set velocity trim value */
- proto_tree_add_item(tree, hf_cip_vel_trim, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
- if ( (cmd_data_set & COMMAND_DATA_SET_ACCELERATION_TRIM) == COMMAND_DATA_SET_ACCELERATION_TRIM )
- {
- /* Display the command data set acceleration trim value */
- proto_tree_add_item(tree, hf_cip_accel_trim, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
- if ( (cmd_data_set & COMMAND_DATA_SET_TORQUE_TRIM) == COMMAND_DATA_SET_TORQUE_TRIM )
- {
- /* Display the command data set torque trim value */
- proto_tree_add_item(tree, hf_cip_trq_trim, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
return bytes_used;
}
bytes_used += 4;
}
- if ( (act_data_set & ACTUAL_DATA_SET_TORQUE) == ACTUAL_DATA_SET_TORQUE )
- {
- /* Display the actual data set torque feedback value */
- proto_tree_add_item(tree, hf_cip_act_trq, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
- if ( (act_data_set & ACTUAL_DATA_SET_CURRENT) == ACTUAL_DATA_SET_CURRENT )
- {
- /* Display the actual data set current feedback value */
- proto_tree_add_item(tree, hf_cip_act_crnt, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
- if ( (act_data_set & ACTUAL_DATA_SET_VOLTAGE) == ACTUAL_DATA_SET_VOLTAGE )
- {
- /* Display the actual data set voltage feedback value */
- proto_tree_add_item(tree, hf_cip_act_volts, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
- if ( (act_data_set & ACTUAL_DATA_SET_FREQUENCY) == ACTUAL_DATA_SET_FREQUENCY )
- {
- /* Display the actual data set frequency feedback value */
- proto_tree_add_item(tree, hf_cip_act_freq, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
- }
-
return bytes_used;
}
dissect_status_data_set(guint32 status_data_set, proto_tree* tree, tvbuff_t* tvb, guint32 offset)
{
guint32 bytes_used = 0;
- proto_item *temp_proto_item;
- proto_tree *temp_proto_tree;
/* The order of these if statements is VERY important, this is the order the values will
* appear in the cyclic data */
if ( (status_data_set & STATUS_DATA_SET_AXIS_STATUS) == STATUS_DATA_SET_AXIS_STATUS )
{
/* Display the various axis state values from the device */
- temp_proto_item = proto_tree_add_item(tree, hf_cip_axis_status, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree( temp_proto_item, ett_axis_status_set );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_local_ctrl, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_alarm, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_dc_bus, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_pwr_struct, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_tracking, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_pos_lock, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_vel_lock, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_vel_standstill, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_vel_threshold, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_vel_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_acc_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_dec_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_torque_threshold, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_torque_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_cur_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_therm_limit, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_feedback_integ, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_shutdown, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- proto_tree_add_item( temp_proto_tree, hf_cip_axis_sts_in_process, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN );
- bytes_used += 4;
+ bytes_used += dissect_axis_status(NULL, tree, NULL, tvb, offset + bytes_used, 4);
proto_tree_add_item(tree, hf_cip_axis_status_mfg, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN);
bytes_used += 4;
bytes_used += 4;
}
- if ( (status_data_set & STATUS_DATA_SET_DRIVE_SAFETY) == STATUS_DATA_SET_DRIVE_SAFETY )
- {
- proto_tree_add_item(tree, hf_cip_drive_safety_status, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN);
- bytes_used += 4;
- }
-
return bytes_used;
}
* as their starting offset
*/
static guint32
-dissect_cntr_cyclic(guint32 con_format _U_, tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance _U_)
+dissect_cntr_cyclic(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
{
proto_item *temp_proto_item;
proto_tree *header_tree, *temp_proto_tree;
/* Add the control mode header field to the tree */
proto_tree_add_item(header_tree, hf_cip_motor_cntrl, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- /* Add the feedback config header field to the tree */
- proto_tree_add_item(header_tree, hf_cip_fdbk_config, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
+ /* Add the feedback mode header field to the tree */
+ proto_tree_add_item(header_tree, hf_cip_feedback_mode, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
/* Add the axis control field to the tree */
proto_tree_add_item(header_tree, hf_cip_axis_control, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
- /* Add the control status to the tree */
- proto_tree_add_item(header_tree, hf_cip_control_status, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
+ dissect_control_status(NULL, header_tree, NULL, tvb, offset + 3, 1);
/* Read the command control header field from the packet into memory and determine if the dissector
* should be using an LREAL or DINT for position */
/* Read the command data set header field from the packet into memory */
temp_data = tvb_get_guint8(tvb, offset + 4);
- /* Create the tree for the command data set header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_cmd_data_set, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_command_data_set);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_pos_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_vel_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_acc_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_trq_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_pos_trim_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_vel_trim_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_acc_trim_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_cmd_data_trq_trim_cmd, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
+ dissect_command_data_set_bits(NULL, header_tree, NULL, tvb, offset + 4, 1);
/* Display the command data values from the cyclic data payload within the command data set tree, the
* cyclic data starts immediately after the interpolation control field in the controller to device
* direction */
- bytes_used += dissect_cmd_data_set(temp_data, temp_proto_tree, tvb, offset + 8 + bytes_used, lreal_pos);
-
- /* Create the tree for the actual data set header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_act_data_set, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_actual_data_set);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_pos, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_vel, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_acc, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_trq, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_crnt, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_vltg, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_fqcy, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
+ bytes_used += dissect_cmd_data_set(temp_data, header_tree, tvb, offset + 8 + bytes_used, lreal_pos);
+
+ dissect_actual_data_set_bits(NULL, header_tree, NULL, tvb, offset + 5, 1);
/* Create the tree for the status data set header field */
temp_proto_item = proto_tree_add_item(header_tree, hf_cip_sts_data_set, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_sts, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_iosts, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_axis_safety, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_sts_drive_safety, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
- /* Create the tree for the command control header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_command_control, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_command_control);
-
- /* Display the interpolation control and position format fields */
- proto_tree_add_item(temp_proto_tree, hf_cip_intrp, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_position_data_type, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
+ dissect_command_control(NULL, header_tree, NULL, tvb, offset + 7, 1);
/* Return the offset to the next byte in the message */
return offset + 8 + bytes_used;
}
/*
- * Function name: dissect_devce_cyclic
+ * Function name: dissect_device_cyclic
*
* Purpose: Dissect the cyclic data block of a device to controller format message
*
* as their starting offset
*/
static guint32
-dissect_devce_cyclic(guint32 con_format _U_, tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance _U_)
+dissect_device_cyclic(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
{
proto_item *temp_proto_item;
proto_tree *header_tree, *temp_proto_tree;
/* Add the control mode header field to the tree */
proto_tree_add_item(header_tree, hf_cip_motor_cntrl, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- /* Add the feedback config header field to the tree */
- proto_tree_add_item(header_tree, hf_cip_fdbk_config, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
+ /* Add the feedback mode header field to the tree */
+ proto_tree_add_item(header_tree, hf_cip_feedback_mode, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
/* Add the axis response field to the tree */
proto_tree_add_item(header_tree, hf_cip_axis_response, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
/* Read the actual data set header field from the packet into memory */
temp_data = tvb_get_guint8(tvb, offset + 5);
- /* Create the tree for the actual data set header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_act_data_set, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_actual_data_set);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_pos, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_vel, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_acc, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_trq, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_crnt, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_vltg, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_act_data_fqcy, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
+ dissect_actual_data_set_bits(NULL, header_tree, NULL, tvb, offset + 5, 1);
/* Display the actual data values from the cyclic data payload within the command data set tree, the
* cyclic data starts immediately after the interpolation control field in the controller to device
* direction and the actual data starts immediately after the cyclic data */
- bytes_used += dissect_act_data_set(temp_data, temp_proto_tree, tvb, offset + 8 + bytes_used);
+ bytes_used += dissect_act_data_set(temp_data, header_tree, tvb, offset + 8 + bytes_used);
/* Read the status data set header field from the packet into memory */
temp_data = tvb_get_guint8(tvb, offset + 6);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_sts, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_iosts, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(temp_proto_tree, hf_cip_sts_axis_safety, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_sts_drive_safety, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
/* Display the status data values from the cyclic data payload within the status data set tree, the
* cyclic data starts immediately after the axis state field in the device to controller
static guint32
dissect_cntr_event(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
{
- proto_item *temp_proto_item;
- proto_tree *header_tree, *temp_proto_tree;
+ proto_tree *header_tree;
guint32 temp_data;
guint32 acks, cur_ack;
guint32 bytes_used = 0;
/* Read the event checking control header field from the packet into memory */
temp_data = tvb_get_letohl(tvb, offset);
- /* Create the tree for the event checking control header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_event_checking, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_event_check_ctrl);
-
- /* Add the individual elements of the event checking control */
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg1_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg1_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg2_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg2_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg1_posrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg1_negrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg2_posrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_reg2_negrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_marker_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_marker_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_pp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_pm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_mp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_home_mm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_ctrl_acks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- /* The dissector will indicate if the protocol is requesting an extended event format but will not dissect it,
- * to date no products actually support this format */
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_extend_format, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ dissect_event_checking_control(NULL, header_tree, NULL, tvb, offset, 4);
/* The event checking control value is 4 bytes long */
bytes_used = 4;
static guint32
dissect_devce_event(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
{
- proto_item *temp_proto_item;
- proto_tree *header_tree, *temp_proto_tree;
+ proto_tree *header_tree;
guint64 temp_data;
guint64 nots, cur_not;
guint32 bytes_used = 0;
/* Read the event checking control header field from the packet into memory */
temp_data = tvb_get_letohl(tvb, offset);
- /* Create the tree for the event checking control header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_event_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_event_check_sts);
-
- /* Add the individual elements of the event checking control */
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg1_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg1_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg2_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg2_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg1_posrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg1_negrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg2_posrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_reg2_negrearm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_marker_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_marker_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_neg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_pp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_pm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_mp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_home_mm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_sts_nfs, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- /* The dissector will indicate if the protocol is requesting an extended event format but will not dissect it,
- * to date no products actually support this format */
- proto_tree_add_item(temp_proto_tree, hf_cip_evnt_extend_format, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ dissect_event_checking_status(NULL, header_tree, NULL, tvb, offset, 4);
/* The event status control value is 4 bytes long */
bytes_used = 4;
* Returns: None
*/
static void
-dissect_get_axis_attr_list_request (tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_get_axis_attr_list_request(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_item *attr_item;
proto_tree *header_tree, *attr_tree;
- guint16 attribute, attribute_cnt;
guint32 local_offset;
- guint8 increment_size, dimension;
/* Create the tree for the get axis attribute list request */
header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL, "Get Axis Attribute List Request");
/* Read the number of attributes that are contained within the request */
- attribute_cnt = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_cnt;
+ proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN, &attribute_cnt);
/* Start the attribute loop at the beginning of the first attribute in the list */
local_offset = offset + 4;
/* For each attribute display the associated fields */
- for (attribute = 0; attribute < attribute_cnt; attribute++)
+ for (guint32 attribute = 0; attribute < attribute_cnt; attribute++)
{
/* At a minimum the local offset needs will need to be incremented by 4 bytes to reach the next attribute */
- increment_size = 4;
-
- /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
- * properly displaying of the attribute is possible */
- dimension = tvb_get_guint8(tvb, local_offset + 2);
+ guint8 increment_size = 4;
/* Create the tree for this attribute within the request */
- attr_item = proto_tree_add_item(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_id;
+ attr_item = proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN, &attribute_id);
attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
- proto_tree_add_item(attr_tree, hf_get_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN);
+ guint32 dimension;
+ proto_tree_add_item_ret_uint(attr_tree, hf_get_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN, &dimension);
proto_tree_add_item(attr_tree, hf_get_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN);
if (dimension == 1)
{
- /* Display the start index and start index from the request if this is an array request */
+ /* Display the start index and start index from the request */
proto_tree_add_item(attr_tree, hf_get_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(attr_tree, hf_get_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN);
increment_size += 4;
}
+ attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION, instance_id, attribute_id);
+ if (pattribute != NULL)
+ {
+ proto_item_append_text(attr_item, " (%s)", pattribute->text);
+ }
+
/* Move the local offset to the next attribute */
local_offset += increment_size;
}
}
+static int dissect_motion_attribute(packet_info *pinfo, tvbuff_t* tvb, int offset, guint32 attribute_id,
+ guint32 instance_id, proto_item* attr_item, proto_tree* attr_tree, guint8 dimension, guint32 attribute_size)
+{
+ attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION, instance_id, attribute_id);
+ int parsed_len = 0;
+
+ if (pattribute != NULL)
+ {
+ proto_item_append_text(attr_item, " (%s)", pattribute->text);
+
+ // TODO: Handle more dimensions. Unsure about the format when there is more than 1 item.
+ if (dimension <= 1)
+ {
+ parsed_len = dissect_cip_attribute(pinfo, attr_tree, attr_item, tvb, pattribute, offset, attribute_size);
+ }
+ }
+
+ return parsed_len;
+}
+
/*
* Function name: dissect_set_axis_attr_list_request
*
* Returns: None
*/
static void
-dissect_set_axis_attr_list_request (tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_set_axis_attr_list_request(packet_info *pinfo, tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_item *attr_item;
proto_tree *header_tree, *attr_tree;
- guint16 attribute, attribute_cnt, data_elements;
guint32 local_offset;
- guint32 attribute_size;
- guint8 dimension, attribute_start, increment_size;
/* Create the tree for the set axis attribute list request */
header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_set_axis_attribute, NULL, "Set Axis Attribute List Request");
/* Read the number of attributes that are contained within the request */
- attribute_cnt = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_cnt;
+ proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN, &attribute_cnt);
/* Start the attribute loop at the beginning of the first attribute in the list */
local_offset = offset + 4;
/* For each attribute display the associated fields */
- for (attribute = 0; attribute < attribute_cnt; attribute++)
+ for (guint32 attribute = 0; attribute < attribute_cnt; attribute++)
{
/* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
- increment_size = 4;
+ guint8 increment_size = 4;
/* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
- * properly displaying of the attribute is possible */
- dimension = tvb_get_guint8(tvb, local_offset + 2);
- attribute_size = tvb_get_guint8(tvb, local_offset + 3);
- attribute_start = 4;
+ * properly displaying of the attribute is possible */
+ guint8 attribute_start = 4;
+
+ /* Create the tree for this attribute in the get axis attribute list request */
+ guint32 attribute_id;
+ attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN, &attribute_id);
+ attr_tree = proto_item_add_subtree(attr_item, ett_set_axis_attr_list);
+
+ guint32 dimension;
+ proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN, &dimension);
+
+ guint32 attribute_size;
+ proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN, &attribute_size);
if (dimension == 1)
{
- data_elements = tvb_get_letohs(tvb, local_offset + 6);
+ guint32 data_elements;
+
+ /* Display the start index and start index from the request if the request is an array */
+ proto_tree_add_item(attr_tree, hf_set_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN, &data_elements);
/* Modify the size of the attribute data by the number of elements if the request is an array request */
attribute_size *= data_elements;
attribute_start += 4;
}
- /* Create the tree for this attribute in the get axis attribute list request */
- attr_item = proto_tree_add_item(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN);
- attr_tree = proto_item_add_subtree(attr_item, ett_set_axis_attr_list);
-
- proto_tree_add_item(attr_tree, hf_set_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(attr_tree, hf_set_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN);
+ int parsed_len = dissect_motion_attribute(pinfo, tvb, local_offset + attribute_start, attribute_id,
+ instance_id, attr_item, attr_tree, dimension, attribute_size);
- if (dimension == 1)
+ // Display any remaining unparsed attribute data.
+ if ((attribute_size - parsed_len) > 0)
{
- /* Display the start index and start index from the request if the request is an array */
- proto_tree_add_item(attr_tree, hf_set_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(attr_tree, hf_set_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start + parsed_len, attribute_size - parsed_len, ENC_NA);
}
- /* Display the value of this attribute */
- proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start, attribute_size, ENC_NA);
-
/* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
if (attribute_size % 4 != 0)
{
* as their starting offset
*/
static guint32
-dissect_cntr_service(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_cntr_service(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_tree *header_tree;
- guint8 service;
+ guint32 service;
/* Create the tree for the entire service data block */
header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_service, NULL, "Service Data Block");
proto_tree_add_item(header_tree, hf_cip_svc_transction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
/* Display the service code */
- service = tvb_get_guint8(tvb, offset + 1);
- proto_tree_add_item(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item_ret_uint(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN, &service);
/* If the service is a set axis, get axis attribute or group sync request dissect it as well */
- switch(service)
+ if (size > 4)
{
- case SC_GET_AXIS_ATTRIBUTE_LIST:
- dissect_get_axis_attr_list_request(tvb, header_tree, offset + 4, size);
- break;
- case SC_SET_AXIS_ATTRIBUTE_LIST:
- dissect_set_axis_attr_list_request(tvb, header_tree, offset + 4, size);
- break;
- case SC_GROUP_SYNC:
- dissect_group_sync_request(tvb, header_tree, offset + 4, size);
- break;
- default:
- /* Display the remainder of the service channel data */
- proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA);
+ switch (service)
+ {
+ case SC_GET_AXIS_ATTRIBUTE_LIST:
+ dissect_get_axis_attr_list_request(tvb, header_tree, offset + 4, size - 4, instance_id);
+ break;
+ case SC_SET_AXIS_ATTRIBUTE_LIST:
+ dissect_set_axis_attr_list_request(pinfo, tvb, header_tree, offset + 4, size - 4, instance_id);
+ break;
+ case SC_GROUP_SYNC:
+ dissect_group_sync_request(tvb, header_tree, offset + 4, size - 4);
+ break;
+ default:
+ /* Display the remainder of the service channel data */
+ proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA);
+ }
}
return offset + size;
* Returns: None
*/
static void
-dissect_set_axis_attr_list_response (tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_set_axis_attr_list_response(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_item *attr_item;
proto_tree *header_tree, *attr_tree;
- guint16 attribute, attribute_cnt;
guint32 local_offset;
/* Create the tree for the set axis attribute list response */
header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL, "Set Axis Attribute List Response");
/* Read the number of attributes that are contained within the response */
- attribute_cnt = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_cnt;
+ proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN, &attribute_cnt);
/* Start the attribute loop at the beginning of the first attribute in the list */
local_offset = offset + 4;
/* For each attribute display the associated fields */
- for (attribute = 0; attribute < attribute_cnt; attribute++)
+ for (guint32 attribute = 0; attribute < attribute_cnt; attribute++)
{
/* Create the tree for the current attribute in the set axis attribute list response */
- attr_item = proto_tree_add_item(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_id;
+ attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN, &attribute_id);
attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
/* Add the response status to the tree */
proto_tree_add_item(attr_tree, hf_cip_svc_set_axis_attr_sts, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN);
+ attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION, instance_id, attribute_id);
+ if (pattribute != NULL)
+ {
+ proto_item_append_text(attr_item, " (%s)", pattribute->text);
+ }
+
/* Move the local offset to the next attribute */
local_offset += 4;
}
* Returns: None
*/
static void
-dissect_get_axis_attr_list_response (tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_get_axis_attr_list_response(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_item *attr_item;
proto_tree *header_tree, *attr_tree;
- guint16 attribute, attribute_cnt, data_elements;
- guint32 attribute_size;
- guint8 dimension, attribute_start, increment_size;
guint32 local_offset;
/* Create the tree for the get axis attribute list response */
header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL, "Get Axis Attribute List Response");
/* Read the number of attributes that are contained within the request */
- attribute_cnt = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_cnt;
+ proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN, &attribute_cnt);
/* Start the attribute loop at the beginning of the first attribute in the list */
local_offset = offset + 4;
/* For each attribute display the associated fields */
- for (attribute = 0; attribute < attribute_cnt; attribute++)
+ for (guint32 attribute = 0; attribute < attribute_cnt; attribute++)
{
/* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
- increment_size = 4;
+ guint8 increment_size = 4;
- /* Pull the fields for this attribute from the payload, all fields are need to make some calculations before
+ /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
* properly displaying of the attribute is possible */
- dimension = tvb_get_guint8(tvb, local_offset + 2);
- attribute_size = tvb_get_guint8(tvb, local_offset + 3);
- attribute_start = 4;
+ guint8 dimension = tvb_get_guint8(tvb, local_offset + 2);
+ guint32 attribute_size = tvb_get_guint8(tvb, local_offset + 3);
+ guint8 attribute_start = 4;
if (dimension == 1)
{
- data_elements = tvb_get_letohs(tvb, local_offset + 6);
+ guint16 data_elements = tvb_get_letohs(tvb, local_offset + 6);
/* Modify the size of the attribute data by the number of elements if the request is an array request */
attribute_size *= data_elements;
}
/* Display the fields associated with the get axis attribute list response */
- attr_item = proto_tree_add_item(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN);
+ guint32 attribute_id;
+ attr_item = proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN, &attribute_id);
attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
if (dimension == 0xFF)
if (dimension == 1)
{
- /* Display the start index and start indexfrom the request */
+ /* Display the start index and start index from the request */
proto_tree_add_item(attr_tree, hf_get_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(attr_tree, hf_get_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN);
}
+ int parsed_len = dissect_motion_attribute(pinfo, tvb, local_offset + attribute_start, attribute_id,
+ instance_id, attr_item, attr_tree, dimension, attribute_size);
+
/* Display the remainder of the service channel data */
- proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, offset + attribute_start, attribute_size, ENC_NA);
+ if ((attribute_size - parsed_len) > 0)
+ {
+ proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start + parsed_len, attribute_size - parsed_len, ENC_NA);
+ }
/* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
if (attribute_size % 4 != 0)
* Returns: None
*/
static void
-dissect_group_sync_response (tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size _U_)
+dissect_group_sync_response (tvbuff_t* tvb, proto_tree* tree, guint32 offset)
{
proto_tree_add_item(tree, hf_cip_group_sync, tvb, offset, 1, ENC_LITTLE_ENDIAN);
}
* as their starting offset
*/
static guint32
-dissect_devce_service(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint32 size)
+dissect_devce_service(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, guint32 offset, guint32 size, guint32 instance_id)
{
proto_tree *header_tree;
proto_tree_add_item(header_tree, hf_cip_svc_transction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
/* Display the service code */
- proto_tree_add_item(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
+ guint32 service_code;
+ proto_tree_add_item_ret_uint(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN, &service_code);
/* Display the general status code */
proto_tree_add_item(header_tree, hf_cip_svc_sts, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(header_tree, hf_cip_svc_ext_status, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
/* If the service is a set axis, get axis attribute response or group sync dissect it as well */
- switch(tvb_get_guint8(tvb, offset + 1))
+ if (size > 4)
{
- case SC_GET_AXIS_ATTRIBUTE_LIST:
- dissect_get_axis_attr_list_response(tvb, header_tree, offset + 4, size);
- break;
- case SC_SET_AXIS_ATTRIBUTE_LIST:
- dissect_set_axis_attr_list_response(tvb, header_tree, offset + 4, size);
- break;
- case SC_GROUP_SYNC:
- dissect_group_sync_response(tvb, header_tree, offset + 4, size);
- break;
- default:
- /* Display the remainder of the service channel data */
- proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA);
+ switch (service_code)
+ {
+ case SC_GET_AXIS_ATTRIBUTE_LIST:
+ dissect_get_axis_attr_list_response(pinfo, tvb, header_tree, offset + 4, size - 4, instance_id);
+ break;
+ case SC_SET_AXIS_ATTRIBUTE_LIST:
+ dissect_set_axis_attr_list_response(tvb, header_tree, offset + 4, size - 4, instance_id);
+ break;
+ case SC_GROUP_SYNC:
+ dissect_group_sync_response(tvb, header_tree, offset + 4);
+ break;
+ default:
+ /* Display the remainder of the service channel data */
+ proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA);
+ break;
+ }
}
return offset + size;
dissect_var_inst_header(tvbuff_t* tvb, proto_tree* tree, guint32 offset, guint8* inst_number, guint32* cyc_size,
guint32* cyc_blk_size, guint32* evnt_size, guint32* servc_size)
{
- guint8 temp_data;
proto_tree *header_tree;
/* Create the tree for the entire instance data header */
proto_tree_add_item(header_tree, hf_var_devce_instance, tvb, offset, 1, ENC_LITTLE_ENDIAN);
/* The "size" fields in the instance data block header are all stored as number of 32-bit words the
- * block uses since all blocks should pad up to 32-bits so to convert to bytes each is mulitplied by 4 */
+ * block uses since all blocks should pad up to 32-bits so to convert to bytes each is multiplied by 4 */
/* Read the instance block size field in bytes from the instance data header */
- temp_data = tvb_get_guint8(tvb, offset + 2);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_instance_block_size,
- tvb, offset + 2, 1, temp_data, "%d words", temp_data);
+ proto_tree_add_item(header_tree, hf_var_devce_instance_block_size, tvb, offset + 2, 1, ENC_NA);
/* Read the cyclic block size field in bytes from the instance data header */
- temp_data = tvb_get_guint8(tvb, offset + 3);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_cyclic_block_size,
- tvb, offset + 3, 1, temp_data, "%d words", temp_data);
+ proto_tree_add_item(header_tree, hf_var_devce_cyclic_block_size, tvb, offset + 3, 1, ENC_NA);
/* Read the cyclic command block size field in bytes from the instance data header */
*cyc_size = (tvb_get_guint8(tvb, offset + 4) * 4);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_cyclic_data_block_size,
- tvb, offset + 4, 1, (*cyc_size)/4, "%d words", (*cyc_size)/4);
+ proto_tree_add_item(header_tree, hf_var_devce_cyclic_data_block_size, tvb, offset + 4, 1, ENC_NA);
/* Read the cyclic write block size field in bytes from the instance data header */
*cyc_blk_size = (tvb_get_guint8(tvb, offset + 5) * 4);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_cyclic_rw_block_size,
- tvb, offset + 5, 1, (*cyc_blk_size)/4, "%d words", (*cyc_blk_size)/4);
+ proto_tree_add_item(header_tree, hf_var_devce_cyclic_rw_block_size, tvb, offset + 5, 1, ENC_NA);
/* Read the event block size in bytes from the instance data header */
*evnt_size = (tvb_get_guint8(tvb, offset + 6) * 4);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_event_block_size,
- tvb, offset + 6, 1, (*evnt_size)/4, "%d words", (*evnt_size)/4);
+ proto_tree_add_item(header_tree, hf_var_devce_event_block_size, tvb, offset + 6, 1, ENC_NA);
/* Read the service block size in bytes from the instance data header */
*servc_size = (tvb_get_guint8(tvb, offset + 7) * 4);
- proto_tree_add_uint_format_value(header_tree, hf_var_devce_service_block_size,
- tvb, offset + 7, 1, (*servc_size)/4, "%d words", (*servc_size)/4);
+ proto_tree_add_item(header_tree, hf_var_devce_service_block_size, tvb, offset + 7, 1, ENC_NA);
}
/*
dissect_var_cont_conn_header(tvbuff_t* tvb, proto_tree* tree, guint32* inst_count, guint32 offset)
{
guint32 header_size;
- guint32 temp_data;
proto_item *temp_proto_item;
proto_tree *header_tree, *temp_proto_tree;
/* Calculate the header size, start with the basic header size */
header_size = 8;
- temp_data = tvb_get_guint8(tvb, offset + 7);
+ guint32 time_data_set = tvb_get_guint8(tvb, offset + 7);
/* Check the time data set field for enabled bits. If either update period or
* update time stamp fields are set, bump the header size by the appropriate size */
- if ( (temp_data & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
+ if ( (time_data_set & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
{
header_size += 8;
}
- if ( (temp_data & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
+ if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
{
header_size += 8;
}
proto_tree_add_item(header_tree, hf_cip_revision, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(header_tree, hf_cip_updateid, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
- /* Create the tree for the node control header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_node_control, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_node_control);
-
- /* Add the individual data elements to the node control tree */
- proto_tree_add_item(temp_proto_tree, hf_cip_node_control_remote, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_control_sync, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_data_valid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_fault_reset, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
-
- /* Read the instance count field from the packet into memory, this gets passed back out of the method */
- *inst_count = tvb_get_guint8(tvb, offset + 4);
+ dissect_node_control(NULL, header_tree, NULL, tvb, offset + 3, 1);
/* Add the instance count and last update id to the connection header tree */
- proto_tree_add_item(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item_ret_uint(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN, inst_count);
proto_tree_add_item(header_tree, hf_cip_last_update, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
- /* Read the time data set from the packet into memory */
- temp_data = tvb_get_guint8(tvb, offset + 7);
-
/* Create the tree for the time data set field */
temp_proto_item = proto_tree_add_item(header_tree, hf_cip_time_data_set, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_time_data_set);
offset = (offset + 7 + 1);
/* Add the time values if they are present in the time data set header field */
- if ( (temp_data & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
+ if ( (time_data_set & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
{
proto_tree_add_item(header_tree, hf_cip_cont_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset = (offset + 8);
}
- if ( (temp_data & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
+ if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
{
proto_tree_add_item(header_tree, hf_cip_cont_time_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset = (offset + 8);
dissect_var_devce_conn_header(tvbuff_t* tvb, proto_tree* tree, guint32* inst_count, guint32 offset)
{
guint32 header_size;
- guint32 temp_data;
proto_item *temp_proto_item;
proto_tree *header_tree, *temp_proto_tree;
/* Calculate the header size, start with the basic header size */
header_size = 8;
- temp_data = tvb_get_guint8(tvb, offset + 7);
- if ( (temp_data & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
+ guint32 time_data_set = tvb_get_guint8(tvb, offset + 7);
+ if ( (time_data_set & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
{
header_size += 8;
}
- if ( (temp_data & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
+ if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
{
header_size += 8;
}
- if ( (temp_data & TIME_DATA_SET_UPDATE_DIAGNOSTICS) == TIME_DATA_SET_UPDATE_DIAGNOSTICS )
+ if ( (time_data_set & TIME_DATA_SET_UPDATE_DIAGNOSTICS) == TIME_DATA_SET_UPDATE_DIAGNOSTICS )
{
header_size += 4;
}
- if ( (temp_data & TIME_DATA_SET_TIME_DIAGNOSTICS) == TIME_DATA_SET_TIME_DIAGNOSTICS )
+ if ( (time_data_set & TIME_DATA_SET_TIME_DIAGNOSTICS) == TIME_DATA_SET_TIME_DIAGNOSTICS )
{
header_size += 16;
}
proto_tree_add_item(header_tree, hf_cip_revision, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(header_tree, hf_cip_updateid, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
- /* Create the tree for the node status header field */
- temp_proto_item = proto_tree_add_item(header_tree, hf_cip_node_status, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_node_status);
-
- /* Add the individual data elements to the node control tree */
- proto_tree_add_item(temp_proto_tree, hf_cip_node_control_remote, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_control_sync, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_data_valid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(temp_proto_tree, hf_cip_node_device_faulted, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
-
- /* Read the instance count field from the packet into memory, this gets passed back out of the method */
- *inst_count = tvb_get_guint8(tvb, offset + 4);
+ dissect_node_status(NULL, header_tree, NULL, tvb, offset + 3, 1);
/* Add the instance count to the connection header tree */
- proto_tree_add_item(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item_ret_uint(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN, inst_count);
/* The device to controller header contains the node alarms and node faults fields as well. */
proto_tree_add_item(header_tree, hf_cip_node_fltalarms, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
/* Add the last update id to the connection header tree */
proto_tree_add_item(header_tree, hf_cip_last_update, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
- /* Read the time data set from the packet into memory */
- temp_data = tvb_get_guint8(tvb, offset + 7);
-
/* Create the tree for the time data set field */
temp_proto_item = proto_tree_add_item(header_tree, hf_cip_time_data_set, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
temp_proto_tree = proto_item_add_subtree(temp_proto_item, ett_time_data_set);
offset = (offset + 7 + 1);
/* Add the time values if they are present in the time data set header field */
- if ( (temp_data & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
+ if ( (time_data_set & TIME_DATA_SET_TIME_STAMP) == TIME_DATA_SET_TIME_STAMP )
{
proto_tree_add_item(header_tree, hf_cip_devc_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset = (offset + 8);
}
- if ( (temp_data & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
+ if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET) == TIME_DATA_SET_TIME_OFFSET )
{
proto_tree_add_item(header_tree, hf_cip_devc_time_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset = (offset + 8);
}
- if ( (temp_data & TIME_DATA_SET_UPDATE_DIAGNOSTICS) == TIME_DATA_SET_UPDATE_DIAGNOSTICS )
+ if ( (time_data_set & TIME_DATA_SET_UPDATE_DIAGNOSTICS) == TIME_DATA_SET_UPDATE_DIAGNOSTICS )
{
/* If the time diagnostic bit is set then the header contains the count of lost updates, late updates, data
* received time stamp and data transmit time stamp */
offset = (offset + 3);
}
- if ( (temp_data & TIME_DATA_SET_TIME_DIAGNOSTICS) == TIME_DATA_SET_TIME_DIAGNOSTICS )
+ if ( (time_data_set & TIME_DATA_SET_TIME_DIAGNOSTICS) == TIME_DATA_SET_TIME_DIAGNOSTICS )
{
proto_tree_add_item(header_tree, hf_cip_data_rx_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset += 8;
* Returns: void
*/
static int
-dissect_cipmotion(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
+dissect_cipmotion(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
{
+ cip_io_data_input* io_data_input = (cip_io_data_input*)data;
+
guint32 con_format;
-/* guint32 seq_number; */
guint32 update_id;
proto_item *proto_item_top;
proto_tree *proto_tree_top;
guint32 offset = 0;
- /* Pull the CIP class 1 sequence number from the incoming message */
-/* seq_number = tvb_get_letohs(tvb, offset); */
+ guint8 ConnPoint = 2;
+ if (io_data_input && io_data_input->conn_info)
+ {
+ ConnPoint = io_data_input->conn_info->ConnPoint;
+ }
+
+ /* Create display subtree for the protocol by creating an item and then
+ * creating a subtree from the item, the subtree must have been registered
+ * in proto_register_cipmotion already */
+ proto_item_top = proto_tree_add_item(tree, proto_cipmotion, tvb, 0, -1, ENC_NA);
+ proto_tree_top = proto_item_add_subtree(proto_item_top, ett_cipmotion);
+
+ /* Add the CIP class 1 sequence number to the tree */
+ proto_tree_add_item(proto_tree_top, hf_cip_class1_seqnum, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset = (offset + 2);
+ if (ConnPoint >= 3)
+ {
+ dissect_cip_run_idle(tvb, offset, proto_tree_top);
+ offset += 4;
+ }
+
/* Pull the actual values for the connection format and update id from the
* incoming message to be used in the column info */
con_format = tvb_get_guint8(tvb, offset);
update_id = tvb_get_guint8(tvb, offset + 2);
/* Make entries in Protocol column and Info column on summary display */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "Motion");
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Motion");
/* Add connection format and update number to the info column */
col_add_fstr( pinfo->cinfo, COL_INFO, "%s, Update Id: %d",
val_to_str(con_format, cip_con_format_vals, "Unknown connection format (%x)"), update_id );
- /* If tree is not NULL then Wireshark is requesting that the dissection
- * panel be updated with the dissected packet, if tree is NULL then only
- * the summary protocol and info columns need to be updated */
- if ( tree )
+ /* Attempt to classify the incoming header */
+ if (( con_format == FORMAT_VAR_CONTROL_TO_DEVICE ) ||
+ ( con_format == FORMAT_VAR_DEVICE_TO_CONTROL ))
{
- /* Create display subtree for the protocol by creating an item and then
- * creating a subtree from the item, the subtree must have been registered
- * in proto_register_cipmotion already */
- proto_item_top = proto_tree_add_item( tree, proto_cipmotion, tvb, 0, -1, ENC_NA );
- proto_tree_top = proto_item_add_subtree( proto_item_top, ett_cipmotion );
-
- /* Add the CIP class 1 sequence number to the tree */
- proto_tree_add_item( proto_tree_top, hf_cip_class1_seqnum, tvb, 0, 2, ENC_LITTLE_ENDIAN );
-
- /* Attempt to classify the incoming header */
- if (( con_format == FORMAT_VAR_CONTROL_TO_DEVICE ) ||
- ( con_format == FORMAT_VAR_DEVICE_TO_CONTROL ))
+ /* Sizes of the individual channels within the connection */
+ guint32 cyc_size, cyc_blk_size, evnt_size, servc_size;
+ guint32 inst_count = 0, inst;
+
+ /* Dissect the header fields */
+ switch(con_format)
{
- /* Sizes of the individual channels within the connection */
- guint32 cyc_size, cyc_blk_size, evnt_size, servc_size;
- guint32 inst_count = 0, inst;
+ case FORMAT_VAR_CONTROL_TO_DEVICE:
+ offset = dissect_var_cont_conn_header(tvb, proto_tree_top, &inst_count, offset);
+ break;
+ case FORMAT_VAR_DEVICE_TO_CONTROL:
+ offset = dissect_var_devce_conn_header(tvb, proto_tree_top, &inst_count, offset);
+ break;
+ }
- /* Dissect the header fields */
+ /* Repeat the following dissections for each instance within the payload */
+ for( inst = 0; inst < inst_count; inst++ )
+ {
+ /* Actual instance number from header field */
+ guint8 instance;
+
+ /* Dissect the instance data header */
+ dissect_var_inst_header( tvb, proto_tree_top, offset, &instance,
+ &cyc_size, &cyc_blk_size, &evnt_size, &servc_size );
+
+ /* Increment the offset to just beyond the instance header */
+ offset += 8;
+
+ /* Dissect the cyclic command (actual) data if any exists */
+ /* Dissect the cyclic write (read) data if any exists */
+ /* Dissect the event data block if there is any event data */
switch(con_format)
{
case FORMAT_VAR_CONTROL_TO_DEVICE:
- offset = dissect_var_cont_conn_header(tvb, proto_tree_top, &inst_count, offset);
+ if ( cyc_size > 0 )
+ offset = dissect_cntr_cyclic(tvb, proto_tree_top, offset, cyc_size);
+ if ( cyc_blk_size > 0 )
+ offset = dissect_cyclic_wt(tvb, proto_tree_top, offset, cyc_blk_size);
+ if ( evnt_size > 0 )
+ offset = dissect_cntr_event(tvb, proto_tree_top, offset, evnt_size);
+ if ( servc_size > 0 )
+ offset = dissect_cntr_service(tvb, pinfo, proto_tree_top, offset, servc_size, instance);
break;
case FORMAT_VAR_DEVICE_TO_CONTROL:
- offset = dissect_var_devce_conn_header(tvb, proto_tree_top, &inst_count, offset);
+ if ( cyc_size > 0 )
+ offset = dissect_device_cyclic(tvb, proto_tree_top, offset, cyc_size);
+ if ( cyc_blk_size > 0 )
+ offset = dissect_cyclic_rd( tvb, proto_tree_top, offset, cyc_blk_size );
+ if ( evnt_size > 0 )
+ offset = dissect_devce_event(tvb, proto_tree_top, offset, evnt_size);
+ if ( servc_size > 0 )
+ offset = dissect_devce_service(tvb, pinfo, proto_tree_top, offset, servc_size, instance);
break;
}
- /* Repeat the following dissections for each instance within the payload */
- for( inst = 0; inst < inst_count; inst++ )
- {
- /* Actual instance number from header field */
- guint8 instance;
-
- /* Dissect the instance data header */
- dissect_var_inst_header( tvb, proto_tree_top, offset, &instance,
- &cyc_size, &cyc_blk_size, &evnt_size, &servc_size );
-
- /* Increment the offset to just beyond the instance header */
- offset += 8;
-
- /* Dissect the cyclic command (actual) data if any exists */
- /* Dissect the cyclic write (read) data if any exists */
- /* Dissect the event data block if there is any event data */
- switch(con_format)
- {
- case FORMAT_VAR_CONTROL_TO_DEVICE:
- if ( cyc_size > 0 )
- offset = dissect_cntr_cyclic( con_format, tvb, proto_tree_top, offset, cyc_size, instance );
- if ( cyc_blk_size > 0 )
- offset = dissect_cyclic_wt(tvb, proto_tree_top, offset, cyc_blk_size);
- if ( evnt_size > 0 )
- offset = dissect_cntr_event(tvb, proto_tree_top, offset, evnt_size);
- if ( servc_size > 0 )
- offset = dissect_cntr_service(tvb, proto_tree_top, offset, servc_size);
- break;
- case FORMAT_VAR_DEVICE_TO_CONTROL:
- if ( cyc_size > 0 )
- offset = dissect_devce_cyclic( con_format, tvb, proto_tree_top, offset, cyc_size, instance );
- if ( cyc_blk_size > 0 )
- offset = dissect_cyclic_rd( tvb, proto_tree_top, offset, cyc_blk_size );
- if ( evnt_size > 0 )
- offset = dissect_devce_event(tvb, proto_tree_top, offset, evnt_size);
- if ( servc_size > 0 )
- offset = dissect_devce_service(tvb, proto_tree_top, offset, servc_size);
- break;
- }
-
- } /* End of instance for( ) loop */
- }
+ } /* End of instance for( ) loop */
+ }
+
+ // Display any remaining unparsed data.
+ int remain_len = tvb_reported_length_remaining(tvb, offset);
+ if (remain_len > 0)
+ {
+ proto_tree_add_item(proto_tree_top, hf_cip_data, tvb, offset, remain_len, ENC_NA);
}
return tvb_captured_length(tvb);
}
+static int dissect_cipmotion3(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
+{
+ enip_conn_val_t conn_info;
+ conn_info.ConnPoint = 3;
+
+ cip_io_data_input io_data_input;
+ io_data_input.conn_info = &conn_info;
+
+ return dissect_cipmotion(tvb, pinfo, tree, &io_data_input);
+}
+
/*
* Function name: proto_register_cipmotion
*
},
{ &hf_cip_class1_seqnum,
- { "CIP Class 1 Sequence Number", "cipm.class1seqnum",
+ { "CIP Class 1 Sequence Count", "cipm.class1seqnum",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
"Node Control: Data Valid", HFILL}
},
{ &hf_cip_node_fault_reset,
- { "Fault Reset", "cipm.fltrst",
+ { "Node Fault Reset", "cipm.fltrst",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x08,
- "Node Control: Device Fault Reset", HFILL}
+ "Node Control: Node Fault Reset", HFILL}
},
{ &hf_cip_node_device_faulted,
{ "Faulted", "cipm.flt",
"Time Data Set: Time Offset", HFILL}
},
{ &hf_cip_time_data_diag,
- { "Time Update Diagnostics", "cipm.time.update",
+ { "Update Diagnostics", "cipm.time.update",
FT_BOOLEAN, 8, TFS(&tfs_true_false), TIME_DATA_SET_UPDATE_DIAGNOSTICS,
- "Time Data Set: Time Update Diagnostics", HFILL}
+ "Time Data Set: Update Diagnostics", HFILL}
},
{ &hf_cip_time_data_time_diag,
{ "Time Diagnostics", "cipm.time.diag",
FT_UINT8, BASE_DEC, VALS(cip_motor_control_vals), 0,
"Cyclic Data Block: Motor Control Mode", HFILL }
},
- { &hf_cip_fdbk_config,
- { "Feedback Config", "cipm.fdbkcfg",
- FT_UINT8, BASE_DEC, VALS(cip_fdbk_config_vals), 0,
- "Cyclic Data Block: Feedback Configuration", HFILL }
+ { &hf_cip_feedback_mode,
+ { "Feedback Mode", "cipm.feedback_mode",
+ FT_UINT8, BASE_DEC, VALS(cip_feedback_mode_vals), FEEDBACK_MODE_BITS,
+ "Cyclic Data Block: Feedback Mode", HFILL }
},
{ &hf_cip_axis_control,
{ "Axis Control", "cipm.axisctrl",
},
{ &hf_cip_control_status,
{ "Control Status", "cipm.csts",
- FT_UINT8, BASE_DEC, VALS(cip_control_status_vals), 0,
+ FT_UINT8, BASE_DEC, NULL, 0,
"Cyclic Data Block: Axis Control Status", HFILL }
},
+ { &hf_cip_control_status_complete,
+ { "Configuration Complete", "cipm.control_status.complete",
+ FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01,
+ NULL, HFILL } },
+ { &hf_cip_control_status_bus_up,
+ { "Converter Bus Up", "cipm.control_status.bus_up",
+ FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x04,
+ NULL, HFILL } },
+ { &hf_cip_control_status_bus_unload,
+ { "Converter Bus Unload", "cipm.control_status.bus_unload",
+ FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x08,
+ NULL, HFILL } },
+ { &hf_cip_control_status_power_loss,
+ { "Converter AC Power Loss", "cipm.control_status.power_loss",
+ FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x10,
+ NULL, HFILL } },
{ &hf_cip_axis_response,
{ "Axis Response", "cipm.axisresp",
FT_UINT8, BASE_DEC, VALS(cip_axis_response_vals), 0,
FT_BOOLEAN, 8, TFS(&tfs_true_false), COMMAND_DATA_SET_TORQUE,
"Command Data Set: Command Torque", HFILL}
},
- { &hf_cip_cmd_data_pos_trim_cmd,
- { "Position Trim", "cipm.cmd.postrm",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), COMMAND_DATA_SET_POSITION_TRIM,
- "Command Data Set: Position Trim", HFILL}
- },
- { &hf_cip_cmd_data_vel_trim_cmd,
- { "Velocity Trim", "cipm.cmd.veltrm",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), COMMAND_DATA_SET_VELOCITY_TRIM,
- "Command Data Set: Velocity Trim", HFILL}
- },
- { &hf_cip_cmd_data_acc_trim_cmd,
- { "Acceleration Trim", "cipm.cmd.acctrm",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), COMMAND_DATA_SET_ACCELERATION_TRIM,
- "Command Data Set: Acceleration Trim", HFILL}
- },
- { &hf_cip_cmd_data_trq_trim_cmd,
- { "Torque Trim", "cipm.cmd.trqtrm",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), COMMAND_DATA_SET_TORQUE_TRIM,
- "Command Data Set: Torque Trim", HFILL}
- },
-
{ &hf_cip_act_data_pos,
{ "Actual Position", "cipm.act.pos",
FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_POSITION,
- "Acutal Data Set: Actual Position", HFILL}
+ "Actual Data Set: Actual Position", HFILL}
},
{ &hf_cip_act_data_vel,
{ "Actual Velocity", "cipm.act.vel",
FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_ACCELERATION,
"Actual Data Set: Actual Acceleration", HFILL}
},
- { &hf_cip_act_data_trq,
- { "Actual Torque", "cipm.act.trq",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_TORQUE,
- "Actual Data Set: Actual Torque", HFILL}
- },
- { &hf_cip_act_data_crnt,
- { "Actual Current", "cipm.act.crnt",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_CURRENT,
- "Actual Data Set: Actual Current", HFILL}
- },
- { &hf_cip_act_data_vltg,
- { "Actual Voltage", "cipm.act.vltg",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_VOLTAGE,
- "Actual Data Set: Actual Voltage", HFILL}
- },
- { &hf_cip_act_data_fqcy,
- { "Actual Frequency", "cipm.act.fqcy",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), ACTUAL_DATA_SET_FREQUENCY,
- "Actual Data Set: Actual Frequency", HFILL}
- },
-
{ &hf_cip_axis_fault,
{ "Axis Fault Code", "cipm.fault.code",
FT_UINT8, BASE_DEC, NULL, 0,
FT_UINT8, BASE_HEX, NULL, 0,
"Axis Safety Sate", HFILL}
},
- { &hf_cip_drive_safety_status,
- { "Drive Safety Status", "cipm.drivesafetystatus",
- FT_UINT32, BASE_HEX, NULL, 0,
- NULL, HFILL}
- },
{ &hf_cip_sts_flt,
{ "Axis Fault Codes", "cipm.sts.flt",
FT_BOOLEAN, 8, TFS(&tfs_true_false), STATUS_DATA_SET_AXIS_FAULT,
FT_BOOLEAN, 8, TFS(&tfs_true_false), STATUS_DATA_SET_AXIS_SAFETY,
"Status Data Set: Axis Safety Status", HFILL}
},
- { &hf_cip_sts_drive_safety,
- { "Drive Safety Status", "cipm.sts.safety",
- FT_BOOLEAN, 8, TFS(&tfs_true_false), STATUS_DATA_SET_DRIVE_SAFETY,
- "Status Data Set: Drive Safety Status", HFILL}
- },
-
{ &hf_cip_intrp,
- { "Interpolation Control", "cipm.intrp",
+ { "Command Target Update", "cipm.intrp",
FT_UINT8, BASE_DEC, VALS(cip_interpolation_vals), COMMAND_CONTROL_TARGET_UPDATE,
- "Cyclic Data Block: Interpolation Control", HFILL}
+ "Cyclic Data Block: Command Target Update", HFILL}
},
{ &hf_cip_position_data_type,
- { "Position Data Type", "cipm.posdatatype",
+ { "Command Position Data Type", "cipm.posdatatype",
FT_UINT8, BASE_DEC, VALS(cip_pos_data_type_vals), COMMAND_CONTROL_POSITION_DATA_TYPE,
- "Cyclic Data Block: Position Data Type", HFILL }
+ "Cyclic Data Block: Command Position Data Type", HFILL }
},
{ &hf_cip_axis_state,
{ "Axis State", "cipm.axste",
"Cyclic Data Block: Read Status", HFILL }
},
{ &hf_cip_event_checking,
- { "Event Control", "cipm.evntchkcontrol",
+ { "Event Checking Control", "cipm.evntchkcontrol",
FT_UINT32, BASE_HEX, NULL, 0,
"Event Channel: Event Checking Control", HFILL}
},
"Event Channel: Event Acknowledgement", HFILL}
},
{ &hf_cip_event_status,
- { "Event Status", "cipm.evntchkstatus",
+ { "Event Checking Status", "cipm.evntchkstatus",
FT_UINT32, BASE_HEX, NULL, 0,
"Event Channel: Event Checking Status", HFILL}
},
"Event Checking Control: Home-Switch-Marker Minus Minus", HFILL}
},
{ &hf_cip_evnt_ctrl_acks,
- { "Event Acknowledge Blocks", "cipm.evnt.ctrl.acks",
+ { "Event Block Count", "cipm.evnt.ctrl.acks",
FT_UINT32, BASE_DEC, NULL, 0x70000000,
- "Event Checking Control: Event Acknowledge Blocks", HFILL}
+ "Event Checking Control: Event Block Count", HFILL}
},
{ &hf_cip_evnt_extend_format,
{ "Extended Event Format", "cipm.evnt.extend",
"Event Checking Status: Home-Switch-Marker Minus Minus", HFILL}
},
{ &hf_cip_evnt_sts_nfs,
- { "Event Notification Blocks", "cipm.evnt.sts.nfs",
+ { "Event Block Count", "cipm.evnt.sts.nfs",
FT_UINT32, BASE_DEC, NULL, 0x70000000,
- "Event Checking Status: Event Notification Blocks", HFILL}
+ "Event Checking Status: Event Block Count", HFILL}
},
{ &hf_cip_evnt_sts_stat,
},
{ &hf_cip_svc_code,
{ "Service Code", "cipm.svc.code",
- FT_UINT8, BASE_DEC, VALS(cip_sc_vals), 0,
+ FT_UINT8, BASE_HEX, VALS(cip_sc_vals), 0,
"Service Data Block: Service Code", HFILL}
},
{ &hf_cip_svc_sts,
},
{ &hf_var_devce_instance_block_size,
{ "Instance Block Size", "cipm.var_devce.header.instance_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Instance Block Size", HFILL}
},
{ &hf_var_devce_cyclic_block_size,
{ "Cyclic Block Size", "cipm.var_devce.header.cyclic_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Cyclic Block Size", HFILL}
},
{ &hf_var_devce_cyclic_data_block_size,
{ "Cyclic Data Block Size", "cipm.var_devce.header.cyclic_data_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Cyclic Data Block Size", HFILL}
},
{ &hf_var_devce_cyclic_rw_block_size,
{ "Cyclic Read/Write Block Size", "cipm.var_devce.header.cyclic_rw_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Cyclic Read/Write Block Size", HFILL}
},
{ &hf_var_devce_event_block_size,
{ "Event Block Size", "cipm.var_devce.header.event_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Event Block Size", HFILL}
},
{ &hf_var_devce_service_block_size,
{ "Service Block Size", "cipm.var_devce.header.service_block_size",
- FT_UINT8, BASE_DEC, NULL, 0,
+ FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0,
"Variable Device Header: Service Block Size", HFILL}
},
{ &hf_cip_axis_sts_local_ctrl,
{ "Local Control", "cipm.axis.local",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000001,
- "Axis Status Data Set: Local Contol", HFILL }
+ "Axis Status Data Set: Local Control", HFILL }
},
{ &hf_cip_axis_sts_alarm,
{ "Alarm", "cipm.axis.alarm",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000008,
"Axis Status Data Set: Power Struct", HFILL }
},
+ { &hf_cip_axis_sts_flux_up,
+ { "Motor Flux Up", "cipm.axis.flx",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000010,
+ "Axis Status Data Set: Motor Flux Up", HFILL }
+ },
{ &hf_cip_axis_sts_tracking,
{ "Tracking", "cipm.axis.track",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000020,
"Axis Status Data Set: Vel Lock", HFILL }
},
{ &hf_cip_axis_sts_vel_standstill,
- { "Standstill", "cipm.axis.nomo",
+ { "Vel Standstill", "cipm.axis.nomo",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000100,
- "Axis Status Data Set: Standstill", HFILL }
+ "Axis Status Data Set: Vel Standstill", HFILL }
},
{ &hf_cip_axis_sts_vel_threshold,
{ "Vel Threshold", "cipm.axis.vthresh",
"Axis Status Data Set: Acc Limit", HFILL }
},
{ &hf_cip_axis_sts_dec_limit,
- { "Dec Limit", "cipm.axis.dlim",
+ { "Decel Limit", "cipm.axis.dlim",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00001000,
- "Axis Status Data Set: Dec Limit", HFILL }
+ "Axis Status Data Set: Decel Limit", HFILL }
},
{ &hf_cip_axis_sts_torque_threshold,
{ "Torque Threshold", "cipm.axis.tthresh",
FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00080000,
"Axis Status Data Set: In Process", HFILL }
},
-
+ { &hf_cip_axis_sts_dc_bus_unload,
+ { "DC Bus Unload", "cipm.axis.dcunload",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00100000,
+ "Axis Status Data Set: DC Bus Unload", HFILL }
+ },
+ { &hf_cip_axis_sts_ac_pwr_loss,
+ { "AC Power Loss", "cipm.axis.acpwrloss",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00200000,
+ "Axis Status Data Set: AC Power Loss", HFILL }
+ },
+ { &hf_cip_axis_sts_pos_cntrl_mode,
+ { "Pos Control Mode", "cipm.axis.poscntrl",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00400000,
+ "Axis Status Data Set: Position Control Mode", HFILL }
+ },
+ { &hf_cip_axis_sts_vel_cntrl_mode,
+ { "Vel Control Mode", "cipm.axis.velcntrl",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00800000,
+ "Axis Status Data Set: Velocity Control Mode", HFILL }
+ },
+ { &hf_cip_axis_sts_trq_cntrl_mode,
+ { "Torque Control Mode", "cipm.axis.trqcntrl",
+ FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x01000000,
+ "Axis Status Data Set: Torque Control Mode", HFILL }
+ },
{ &hf_cip_act_pos,
{ "Actual Position", "cipm.actpos",
FT_INT32, BASE_DEC, NULL, 0,
FT_FLOAT, BASE_NONE, NULL, 0,
"Cyclic Data Set: Actual Acceleration", HFILL }
},
- { &hf_cip_act_trq,
- { "Actual Torque", "cipm.acttrq",
- FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Actual Torque", HFILL }
- },
- { &hf_cip_act_crnt,
- { "Actual Current", "cipm.actcrnt",
- FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Actual Current", HFILL }
- },
- { &hf_cip_act_volts,
- { "Actual Volts", "cipm.actvolts",
- FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Actual Volts", HFILL }
- },
- { &hf_cip_act_freq,
- { "Actual Frequency", "cipm.actfreq",
- FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Actual Frequency", HFILL }
- },
{ &hf_cip_pos_cmd,
{ "Position Command", "cipm.posfcmd",
FT_DOUBLE, BASE_NONE, NULL, 0,
},
{ &hf_cip_pos_trim,
{ "Position Trim", "cipm.postrim",
- FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Position Trim", HFILL }
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
},
{ &hf_cip_vel_trim,
{ "Velocity Trim", "cipm.veltrim",
FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Velocity Trim", HFILL }
+ NULL, HFILL }
},
{ &hf_cip_accel_trim,
{ "Acceleration Trim", "cipm.acceltrim",
FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Acceleration Trim", HFILL }
+ NULL, HFILL }
},
{ &hf_cip_trq_trim,
{ "Torque Trim", "cipm.trqtrim",
FT_FLOAT, BASE_NONE, NULL, 0,
- "Cyclic Data Set: Torque Trim", HFILL }
+ NULL, HFILL }
+ },
+ { &hf_cip_data,
+ { "Data", "cipm.data",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
}
};
static gint *cip_subtree[] = {
&ett_cipmotion,
&ett_cont_dev_header,
+ &ett_control_status,
&ett_node_control,
&ett_node_status,
&ett_time_data_set,
"Common Industrial Protocol, Motion", /* Full name of protocol */
"CIP Motion", /* Short name of protocol */
"cipm"); /* Abbreviated name of protocol */
-;
+
+ proto_cipmotion3 = proto_register_protocol_in_name_only(
+ "Common Industrial Protocol, Motion - Rev 3",
+ "CIP Motion - Rev 3",
+ "cipm3",
+ proto_cipmotion,
+ FT_PROTOCOL);
+
/* Register the header fields with the protocol */
proto_register_field_array(proto_cipmotion, hf, array_length(hf));
/* Register the subtrees for the protocol dissection */
proto_register_subtree_array(cip_subtree, array_length(cip_subtree));
- register_dissector( "cipmotion", dissect_cipmotion, proto_cipmotion);
+ cipmotion_handle = register_dissector("cipmotion", dissect_cipmotion, proto_cipmotion);
+ cipmotion3_handle = register_dissector("cipmotion3", dissect_cipmotion3, proto_cipmotion3);
}
void proto_reg_handoff_cipmotion(void)
{
- dissector_handle_t cipmotion_handle;
+ dissector_add_for_decode_as("cip.io", cipmotion_handle);
+ dissector_add_for_decode_as("cip.io", cipmotion3_handle);
- /* Create and register dissector for I/O data handling */
- cipmotion_handle = create_dissector_handle( dissect_cipmotion, proto_cipmotion );
- dissector_add_for_decode_as("enip.io", cipmotion_handle );
+ dissector_add_uint("cip.io.iface", CI_CLS_MOTION, cipmotion_handle);
}
/*