2 * Routines for CIP (Common Industrial Protocol) Motion dissection
3 * CIP Motion Home: www.odva.org
6 * Benjamin M. Stocks <bmstocks@ra.rockwell.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include "packet-cip.h"
34 void proto_register_cipmotion(void);
35 /* The entry point to the actual disection is: dissect_cipmotion */
37 /* Protocol handle for CIP Motion */
38 static int proto_cipmotion
= -1;
40 /* Header field identifiers, these are registered in the
41 * proto_register_cipmotion function along with the bites/bytes
43 static int hf_cip_format
= -1;
44 static int hf_cip_revision
= -1;
45 static int hf_cip_class1_seqnum
= -1;
46 static int hf_cip_updateid
= -1;
47 static int hf_cip_instance_cnt
= -1;
48 static int hf_cip_last_update
= -1;
49 static int hf_cip_node_status
= -1;
50 static int hf_cip_node_control
= -1;
51 static int hf_cip_node_control_remote
= -1;
52 static int hf_cip_node_control_sync
= -1;
53 static int hf_cip_node_data_valid
= -1;
54 static int hf_cip_node_fault_reset
= -1;
55 static int hf_cip_node_device_faulted
= -1;
56 static int hf_cip_time_data_set
= -1;
57 static int hf_cip_time_data_stamp
= -1;
58 static int hf_cip_time_data_offset
= -1;
59 static int hf_cip_time_data_diag
= -1;
60 static int hf_cip_time_data_time_diag
= -1;
61 static int hf_cip_cont_time_stamp
= -1;
62 static int hf_cip_cont_time_offset
= -1;
63 static int hf_cip_devc_time_stamp
= -1;
64 static int hf_cip_devc_time_offset
= -1;
65 static int hf_cip_lost_update
= -1;
66 static int hf_cip_late_update
= -1;
67 static int hf_cip_data_rx_time_stamp
= -1;
68 static int hf_cip_data_tx_time_stamp
= -1;
69 static int hf_cip_node_fltalarms
= -1;
70 static int hf_cip_motor_cntrl
= -1;
71 static int hf_cip_fdbk_config
= -1;
72 static int hf_cip_axis_control
= -1;
73 static int hf_cip_control_status
= -1;
74 static int hf_cip_axis_response
= -1;
75 static int hf_cip_axis_resp_stat
= -1;
76 static int hf_cip_cmd_data_pos_cmd
= -1;
77 static int hf_cip_cmd_data_vel_cmd
= -1;
78 static int hf_cip_cmd_data_acc_cmd
= -1;
79 static int hf_cip_cmd_data_trq_cmd
= -1;
80 static int hf_cip_cmd_data_pos_trim_cmd
= -1;
81 static int hf_cip_cmd_data_vel_trim_cmd
= -1;
82 static int hf_cip_cmd_data_acc_trim_cmd
= -1;
83 static int hf_cip_cmd_data_trq_trim_cmd
= -1;
84 static int hf_cip_act_data_pos
= -1;
85 static int hf_cip_act_data_vel
= -1;
86 static int hf_cip_act_data_acc
= -1;
87 static int hf_cip_act_data_trq
= -1;
88 static int hf_cip_act_data_crnt
= -1;
89 static int hf_cip_act_data_vltg
= -1;
90 static int hf_cip_act_data_fqcy
= -1;
91 static int hf_cip_sts_flt
= -1;
92 static int hf_cip_sts_alrm
= -1;
93 static int hf_cip_sts_sts
= -1;
94 static int hf_cip_sts_iosts
= -1;
95 static int hf_cip_sts_safety
= -1;
96 static int hf_cip_intrp
= -1;
97 static int hf_cip_position_data_type
= -1;
98 static int hf_cip_axis_state
= -1;
99 static int hf_cip_evnt_ctrl_reg1_pos
= -1;
100 static int hf_cip_evnt_ctrl_reg1_neg
= -1;
101 static int hf_cip_evnt_ctrl_reg2_pos
= -1;
102 static int hf_cip_evnt_ctrl_reg2_neg
= -1;
103 static int hf_cip_evnt_ctrl_reg1_posrearm
= -1;
104 static int hf_cip_evnt_ctrl_reg1_negrearm
= -1;
105 static int hf_cip_evnt_ctrl_reg2_posrearm
= -1;
106 static int hf_cip_evnt_ctrl_reg2_negrearm
= -1;
107 static int hf_cip_evnt_ctrl_marker_pos
= -1;
108 static int hf_cip_evnt_ctrl_marker_neg
= -1;
109 static int hf_cip_evnt_ctrl_home_pos
= -1;
110 static int hf_cip_evnt_ctrl_home_neg
= -1;
111 static int hf_cip_evnt_ctrl_home_pp
= -1;
112 static int hf_cip_evnt_ctrl_home_pm
= -1;
113 static int hf_cip_evnt_ctrl_home_mp
= -1;
114 static int hf_cip_evnt_ctrl_home_mm
= -1;
115 static int hf_cip_evnt_ctrl_acks
= -1;
116 static int hf_cip_evnt_extend_format
= -1;
117 static int hf_cip_evnt_sts_reg1_pos
= -1;
118 static int hf_cip_evnt_sts_reg1_neg
= -1;
119 static int hf_cip_evnt_sts_reg2_pos
= -1;
120 static int hf_cip_evnt_sts_reg2_neg
= -1;
121 static int hf_cip_evnt_sts_reg1_posrearm
= -1;
122 static int hf_cip_evnt_sts_reg1_negrearm
= -1;
123 static int hf_cip_evnt_sts_reg2_posrearm
= -1;
124 static int hf_cip_evnt_sts_reg2_negrearm
= -1;
125 static int hf_cip_evnt_sts_marker_pos
= -1;
126 static int hf_cip_evnt_sts_marker_neg
= -1;
127 static int hf_cip_evnt_sts_home_pos
= -1;
128 static int hf_cip_evnt_sts_home_neg
= -1;
129 static int hf_cip_evnt_sts_home_pp
= -1;
130 static int hf_cip_evnt_sts_home_pm
= -1;
131 static int hf_cip_evnt_sts_home_mp
= -1;
132 static int hf_cip_evnt_sts_home_mm
= -1;
133 static int hf_cip_evnt_sts_nfs
= -1;
134 static int hf_cip_evnt_sts_stat
= -1;
135 static int hf_cip_evnt_type
= -1;
136 static int hf_cip_svc_code
= -1;
137 static int hf_cip_svc_sts
= -1;
138 static int hf_cip_svc_set_axis_attr_sts
= -1;
139 static int hf_cip_svc_get_axis_attr_sts
= -1;
140 static int hf_cip_svc_transction
= -1;
141 static int hf_cip_svc_ext_status
= -1;
142 static int hf_cip_svc_data
= -1;
143 static int hf_cip_ptp_grandmaster
= -1;
144 static int hf_cip_axis_alarm
= -1;
145 static int hf_cip_axis_fault
= -1;
146 static int hf_cip_axis_sts_local_ctrl
= -1;
147 static int hf_cip_axis_sts_alarm
= -1;
148 static int hf_cip_axis_sts_dc_bus
= -1;
149 static int hf_cip_axis_sts_pwr_struct
= -1;
150 static int hf_cip_axis_sts_tracking
= -1;
151 static int hf_cip_axis_sts_pos_lock
= -1;
152 static int hf_cip_axis_sts_vel_lock
= -1;
153 static int hf_cip_axis_sts_vel_standstill
= -1;
154 static int hf_cip_axis_sts_vel_threshold
= -1;
155 static int hf_cip_axis_sts_vel_limit
= -1;
156 static int hf_cip_axis_sts_acc_limit
= -1;
157 static int hf_cip_axis_sts_dec_limit
= -1;
158 static int hf_cip_axis_sts_torque_threshold
= -1;
159 static int hf_cip_axis_sts_torque_limit
= -1;
160 static int hf_cip_axis_sts_cur_limit
= -1;
161 static int hf_cip_axis_sts_therm_limit
= -1;
162 static int hf_cip_axis_sts_feedback_integ
= -1;
163 static int hf_cip_axis_sts_shutdown
= -1;
164 static int hf_cip_axis_sts_in_process
= -1;
165 static int hf_cip_cyclic_wrt_data
= -1;
166 static int hf_cip_cyclic_rd_data
= -1;
167 static int hf_cip_cyclic_write_blk
= -1;
168 static int hf_cip_cyclic_read_blk
= -1;
169 static int hf_cip_cyclic_write_sts
= -1;
170 static int hf_cip_cyclic_read_sts
= -1;
171 static int hf_cip_attribute_data
= -1;
172 static int hf_cip_event_checking
= -1;
173 static int hf_cip_event_ack
= -1;
174 static int hf_cip_event_status
= -1;
175 static int hf_cip_event_id
= -1;
176 static int hf_cip_event_pos
= -1;
177 static int hf_cip_event_ts
= -1;
178 static int hf_cip_pos_cmd
= -1;
179 static int hf_cip_pos_cmd_int
= -1;
180 static int hf_cip_vel_cmd
= -1;
181 static int hf_cip_accel_cmd
= -1;
182 static int hf_cip_trq_cmd
= -1;
183 static int hf_cip_pos_trim
= -1;
184 static int hf_cip_vel_trim
= -1;
185 static int hf_cip_accel_trim
= -1;
186 static int hf_cip_trq_trim
= -1;
187 static int hf_cip_act_pos
= -1;
188 static int hf_cip_act_vel
= -1;
189 static int hf_cip_act_accel
= -1;
190 static int hf_cip_act_trq
= -1;
191 static int hf_cip_act_crnt
= -1;
192 static int hf_cip_act_volts
= -1;
193 static int hf_cip_act_freq
= -1;
194 static int hf_cip_fault_type
= -1;
195 static int hf_cip_fault_sub_code
= -1;
196 static int hf_cip_fault_action
= -1;
197 static int hf_cip_fault_time_stamp
= -1;
198 static int hf_cip_alarm_type
= -1;
199 static int hf_cip_alarm_sub_code
= -1;
200 static int hf_cip_alarm_state
= -1;
201 static int hf_cip_alarm_time_stamp
= -1;
202 static int hf_cip_axis_status
= -1;
203 static int hf_cip_axis_status_mfg
= -1;
204 static int hf_cip_axis_io_status
= -1;
205 static int hf_cip_axis_io_status_mfg
= -1;
206 static int hf_cip_safety_status
= -1;
207 static int hf_cip_cmd_data_set
= -1;
208 static int hf_cip_act_data_set
= -1;
209 static int hf_cip_sts_data_set
= -1;
210 static int hf_cip_group_sync
= -1;
211 static int hf_cip_command_control
= -1;
213 static int hf_get_axis_attr_list_attribute_cnt
= -1;
214 static int hf_get_axis_attr_list_attribute_id
= -1;
215 static int hf_get_axis_attr_list_dimension
= -1;
216 static int hf_get_axis_attr_list_element_size
= -1;
217 static int hf_get_axis_attr_list_start_index
= -1;
218 static int hf_get_axis_attr_list_data_elements
= -1;
219 static int hf_set_axis_attr_list_attribute_cnt
= -1;
220 static int hf_set_axis_attr_list_attribute_id
= -1;
221 static int hf_set_axis_attr_list_dimension
= -1;
222 static int hf_set_axis_attr_list_element_size
= -1;
223 static int hf_set_axis_attr_list_start_index
= -1;
224 static int hf_set_axis_attr_list_data_elements
= -1;
225 static int hf_var_devce_instance
= -1;
226 static int hf_var_devce_instance_block_size
= -1;
227 static int hf_var_devce_cyclic_block_size
= -1;
228 static int hf_var_devce_cyclic_data_block_size
= -1;
229 static int hf_var_devce_cyclic_rw_block_size
= -1;
230 static int hf_var_devce_event_block_size
= -1;
231 static int hf_var_devce_service_block_size
= -1;
233 /* Subtree pointers for the dissection */
234 static gint ett_cipmotion
= -1;
235 static gint ett_cont_dev_header
= -1;
236 static gint ett_node_control
= -1;
237 static gint ett_node_status
= -1;
238 static gint ett_time_data_set
= -1;
239 static gint ett_inst_data_header
= -1;
240 static gint ett_cyclic_data_block
= -1;
241 static gint ett_control_mode
= -1;
242 static gint ett_feedback_config
= -1;
243 static gint ett_command_data_set
= -1;
244 static gint ett_actual_data_set
= -1;
245 static gint ett_status_data_set
= -1;
246 static gint ett_interp_control
= -1;
247 static gint ett_cyclic_rd_wt
= -1;
248 static gint ett_event
= -1;
249 static gint ett_event_check_ctrl
= -1;
250 static gint ett_event_check_sts
= -1;
251 static gint ett_service
= -1;
252 static gint ett_get_axis_attribute
= -1;
253 static gint ett_set_axis_attribute
= -1;
254 static gint ett_get_axis_attr_list
= -1;
255 static gint ett_set_axis_attr_list
= -1;
256 static gint ett_group_sync
= -1;
257 static gint ett_axis_status_set
= -1;
258 static gint ett_command_control
= -1;
260 /* These are the BITMASKS for the Time Data Set header field */
261 #define TIME_DATA_SET_TIME_STAMP 0x1
262 #define TIME_DATA_SET_TIME_OFFSET 0x2
263 #define TIME_DATA_SET_UPDATE_DIAGNOSTICS 0x4
264 #define TIME_DATA_SET_TIME_DIAGNOSTICS 0x8
266 /* These are the BITMASKS for the Command Data Set cyclic field */
267 #define COMMAND_DATA_SET_POSITION 0x01
268 #define COMMAND_DATA_SET_VELOCITY 0x02
269 #define COMMAND_DATA_SET_ACCELERATION 0x04
270 #define COMMAND_DATA_SET_TORQUE 0x08
271 #define COMMAND_DATA_SET_POSITION_TRIM 0x10
272 #define COMMAND_DATA_SET_VELOCITY_TRIM 0x20
273 #define COMMAND_DATA_SET_ACCELERATION_TRIM 0x40
274 #define COMMAND_DATA_SET_TORQUE_TRIM 0x80
276 /* These are the BITMASKS for the Actual Data Set cyclic field */
277 #define ACTUAL_DATA_SET_POSITION 0x01
278 #define ACTUAL_DATA_SET_VELOCITY 0x02
279 #define ACTUAL_DATA_SET_ACCELERATION 0x04
280 #define ACTUAL_DATA_SET_TORQUE 0x08
281 #define ACTUAL_DATA_SET_CURRENT 0x10
282 #define ACTUAL_DATA_SET_VOLTAGE 0x20
283 #define ACTUAL_DATA_SET_FREQUENCY 0x40
285 /* These are the BITMASKS for the Status Data Set cyclic field */
286 #define STATUS_DATA_SET_AXIS_FAULT 0x01
287 #define STATUS_DATA_SET_AXIS_ALARM 0x02
288 #define STATUS_DATA_SET_AXIS_STATUS 0x04
289 #define STATUS_DATA_SET_AXIS_IO_STATUS 0x08
290 #define STATUS_DATA_SET_AXIS_SAFETY 0x80
292 /* These are the BITMASKS for the Command Control cyclic field */
293 #define COMMAND_CONTROL_TARGET_UPDATE 0x03
294 #define COMMAND_CONTROL_POSITION_DATA_TYPE 0x0C
296 /* These are the VALUES of the connection format header field of the
297 * CIP Motion protocol */
298 #define FORMAT_FIXED_CONTROL_TO_DEVICE 2
299 #define FORMAT_FIXED_DEVICE_TO_CONTROL 3
300 #define FORMAT_VAR_CONTROL_TO_DEVICE 6
301 #define FORMAT_VAR_DEVICE_TO_CONTROL 7
303 /* Translate function to string - connection format values */
304 static const value_string cip_con_format_vals
[] = {
305 { FORMAT_FIXED_CONTROL_TO_DEVICE
, "Fixed Controller-to-Device" },
306 { FORMAT_FIXED_DEVICE_TO_CONTROL
, "Fixed Device-to-Controller" },
307 { FORMAT_VAR_CONTROL_TO_DEVICE
, "Variable Controller-to-Device" },
308 { FORMAT_VAR_DEVICE_TO_CONTROL
, "Variable Device-to-Controller" },
312 /* Translate function to string - motor control mode values */
313 static const value_string cip_motor_control_vals
[] = {
315 { 1, "Position Control" },
316 { 2, "Velocity Control" },
317 { 3, "Acceleration Control" },
318 { 4, "Torque Control" },
319 { 5, "Current Control" },
323 /* Translate function to string - feedback config values */
324 static const value_string cip_fdbk_config_vals
[] = {
325 { 0, "No Feedback" },
326 { 1, "Master Feedback" },
327 { 2, "Motor Feedback" },
328 { 3, "Load Feedback" },
329 { 4, "Dual Feedback" },
333 /* Translate function to string - axis control values */
334 static const value_string cip_axis_control_vals
[] =
337 { 1, "Enable Request" },
338 { 2, "Disble Request" },
339 { 3, "Shutdown Request" },
340 { 4, "Shutdown Reset Request" },
341 { 5, "Abort Request" },
342 { 6, "Fault Reset Request" },
343 { 7, "Stop Process" },
344 { 8, "Change Actual Pos" },
345 { 9, "Change Command Pos Ref" },
346 { 127, "Cancel Request" },
350 /* Translate function to string - control status values */
351 static const value_string cip_control_status_vals
[] =
353 { 1, "Configuration Complete" },
357 /* Translate function to string - group sync Status */
358 static const value_string cip_sync_status_vals
[] =
360 { 0, "Synchronized" },
361 { 1, "Not Synchronized" },
362 { 2, "Wrong Grandmaster" },
366 /* Translate function to string - command target update */
367 static const value_string cip_interpolation_vals
[] = {
369 { 1, "Extrapolate (+1)" },
370 { 2, "Interpolate (+2)" },
374 /* These are the VALUES for the Command Position Data Type */
375 #define POSITION_DATA_LREAL 0x00
376 #define POSITION_DATA_DINT 0x01
378 /* Translate function to string - position data type */
379 static const value_string cip_pos_data_type_vals
[] = {
380 { POSITION_DATA_LREAL
, "LREAL (64-bit Float)" },
381 { POSITION_DATA_DINT
, "DINT (32-bit Integer)" },
385 /* Translate function to string - axis response values */
386 static const value_string cip_axis_response_vals
[] = {
387 { 0, "No Acknowledge" },
388 { 1, "Enable Acknowledge" },
389 { 2, "Disable Acknowledge" },
390 { 3, "Shutdown Acknowledge" },
391 { 4, "Shutdown Reset Acknowledge" },
392 { 5, "Abort Acknowledge" },
393 { 6, "Fault Reset Acknowledge" },
397 /* Translate function to string - axis state values */
398 static const value_string cip_axis_state_vals
[] = {
399 { 0, "Initializing" },
400 { 1, "Pre-charging" },
407 { 8, "Major Faulted" },
408 { 9, "Start Inhibited" },
413 /* Translate function to string - event type values */
414 static const value_string cip_event_type_vals
[] = {
415 { 0, "Registration 1 Positive Edge" },
416 { 1, "Registration 1 Negative Edge" },
417 { 2, "Registration 2 Positive Edge" },
418 { 3, "Registration 2 Negative Edge" },
419 { 4, "Marker Positive Edge" },
420 { 5, "Marker Negative Edge" },
421 { 6, "Home Switch Positive Edge" },
422 { 7, "Home Switch Negative Edge" },
423 { 8, "Home Switch Marker ++" },
424 { 9, "Home Switch Marker +-" },
425 { 10, "Home Switch Marker -+" },
426 { 11, "Home Switch Marker --" },
430 #define SC_GET_AXIS_ATTRIBUTE_LIST 0x4B
431 #define SC_SET_AXIS_ATTRIBUTE_LIST 0x4C
432 #define SC_SET_CYCLIC_WRITE_LIST 0x4D
433 #define SC_SET_CYCLIC_READ_LIST 0x4E
434 #define SC_RUN_MOTOR_TEST 0x4F
435 #define SC_GET_MOTOR_TEST_DATA 0x50
436 #define SC_RUN_INERTIA_TEST 0x51
437 #define SC_GET_INERTIA_TEST_DATA 0x52
438 #define SC_RUN_HOOKUP_TEST 0x53
439 #define SC_GET_HOOKUP_TEST_DATA 0x53
441 /* Translate function to string - CIP Service codes */
442 static const value_string cip_sc_vals
[] = {
444 { SC_GET_AXIS_ATTRIBUTE_LIST
, "Get Axis Attribute List" },
445 { SC_SET_AXIS_ATTRIBUTE_LIST
, "Set Axis Attribute List" },
446 { SC_SET_CYCLIC_WRITE_LIST
, "Set Cyclic Write List" },
447 { SC_SET_CYCLIC_READ_LIST
, "Set Cyclic Read List" },
448 { SC_RUN_MOTOR_TEST
, "Run Motor Test" },
449 { SC_GET_MOTOR_TEST_DATA
, "Get Motor Test Data" },
450 { SC_RUN_INERTIA_TEST
, "Run Inertia Test" },
451 { SC_GET_INERTIA_TEST_DATA
, "Get Intertia Test Data" },
452 { SC_RUN_HOOKUP_TEST
, "Run Hookup Test" },
453 { SC_GET_HOOKUP_TEST_DATA
, "Get Hookup Test Data" },
458 * Function name: dissect_cmd_data_set
460 * Purpose: Dissect the command data set field of the cyclic data block header and if any
461 * of the command value bits are set to retrieve and display those command values
463 * Returns: The number of bytes in the cyclic data used
466 dissect_cmd_data_set(guint32 cmd_data_set
, proto_tree
* tree
, tvbuff_t
* tvb
, guint32 offset
, gboolean lreal_pos
)
468 guint32 bytes_used
= 0;
470 /* The order of these if statements is VERY important, this is the order the values will
471 * appear in the cyclic data */
472 if ( (cmd_data_set
& COMMAND_DATA_SET_POSITION
) == COMMAND_DATA_SET_POSITION
)
474 /* Based on the Command Position Data Type value embedded in the Command Control
475 * header field the position is either 64-bit floating or 32-bit integer */
478 /* Display the command data set position command value */
479 proto_tree_add_item(tree
, hf_cip_pos_cmd
, tvb
, offset
+ bytes_used
, 8, ENC_LITTLE_ENDIAN
);
484 /* Display the command data set position command value */
485 proto_tree_add_item(tree
, hf_cip_pos_cmd_int
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
490 if ( (cmd_data_set
& COMMAND_DATA_SET_VELOCITY
) == COMMAND_DATA_SET_VELOCITY
)
492 /* Display the command data set velocity command value */
493 proto_tree_add_item(tree
, hf_cip_vel_cmd
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
497 if ( (cmd_data_set
& COMMAND_DATA_SET_ACCELERATION
) == COMMAND_DATA_SET_ACCELERATION
)
499 /* Display the command data set acceleration command value */
500 proto_tree_add_item(tree
, hf_cip_accel_cmd
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
504 if ( (cmd_data_set
& COMMAND_DATA_SET_TORQUE
) == COMMAND_DATA_SET_TORQUE
)
506 /* Display the command data set torque command value */
507 proto_tree_add_item(tree
, hf_cip_trq_cmd
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
511 if ( (cmd_data_set
& COMMAND_DATA_SET_POSITION_TRIM
) == COMMAND_DATA_SET_POSITION_TRIM
)
513 /* Display the command data set position trim value */
514 proto_tree_add_item(tree
, hf_cip_pos_trim
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
518 if ( (cmd_data_set
& COMMAND_DATA_SET_VELOCITY_TRIM
) == COMMAND_DATA_SET_VELOCITY_TRIM
)
520 /* Display the command data set velocity trim value */
521 proto_tree_add_item(tree
, hf_cip_vel_trim
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
525 if ( (cmd_data_set
& COMMAND_DATA_SET_ACCELERATION_TRIM
) == COMMAND_DATA_SET_ACCELERATION_TRIM
)
527 /* Display the command data set acceleration trim value */
528 proto_tree_add_item(tree
, hf_cip_accel_trim
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
532 if ( (cmd_data_set
& COMMAND_DATA_SET_TORQUE_TRIM
) == COMMAND_DATA_SET_TORQUE_TRIM
)
534 /* Display the command data set torque trim value */
535 proto_tree_add_item(tree
, hf_cip_trq_trim
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
544 * Function name: dissect_act_data_set
546 * Purpose: Dissect the actual data set field of the cyclic data block header and if any
547 * of the actual value bits are set to retrieve and display those feedback values
549 * Returns: The number of bytes in the cyclic data used
552 dissect_act_data_set(guint32 act_data_set
, proto_tree
* tree
, tvbuff_t
* tvb
, guint32 offset
)
554 guint32 bytes_used
= 0;
556 /* The order of these if statements is VERY important, this is the order the values will
557 * appear in the cyclic data */
558 if ( (act_data_set
& ACTUAL_DATA_SET_POSITION
) == ACTUAL_DATA_SET_POSITION
)
560 /* Display the actual data set position feedback value */
561 proto_tree_add_item(tree
, hf_cip_act_pos
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
565 if ( (act_data_set
& ACTUAL_DATA_SET_VELOCITY
) == ACTUAL_DATA_SET_VELOCITY
)
567 /* Display the actual data set velocity feedback value */
568 proto_tree_add_item(tree
, hf_cip_act_vel
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
572 if ( (act_data_set
& ACTUAL_DATA_SET_ACCELERATION
) == ACTUAL_DATA_SET_ACCELERATION
)
574 /* Display the actual data set acceleration feedback value */
575 proto_tree_add_item(tree
, hf_cip_act_accel
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
579 if ( (act_data_set
& ACTUAL_DATA_SET_TORQUE
) == ACTUAL_DATA_SET_TORQUE
)
581 /* Display the actual data set torque feedback value */
582 proto_tree_add_item(tree
, hf_cip_act_trq
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
585 if ( (act_data_set
& ACTUAL_DATA_SET_CURRENT
) == ACTUAL_DATA_SET_CURRENT
)
587 /* Display the actual data set current feedback value */
588 proto_tree_add_item(tree
, hf_cip_act_crnt
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
592 if ( (act_data_set
& ACTUAL_DATA_SET_VOLTAGE
) == ACTUAL_DATA_SET_VOLTAGE
)
594 /* Display the actual data set voltage feedback value */
595 proto_tree_add_item(tree
, hf_cip_act_volts
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
599 if ( (act_data_set
& ACTUAL_DATA_SET_FREQUENCY
) == ACTUAL_DATA_SET_FREQUENCY
)
601 /* Display the actual data set frequency feedback value */
602 proto_tree_add_item(tree
, hf_cip_act_freq
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
610 * Function name: dissect_status_data_set
612 * Purpose: Dissect the status data set field of the cyclic data block header and if any
613 * of the status value bits are set to retrieve and display those status values
615 * Returns: The number of bytes in the cyclic data used
618 dissect_status_data_set(guint32 status_data_set
, proto_tree
* tree
, tvbuff_t
* tvb
, guint32 offset
)
620 guint32 bytes_used
= 0;
621 proto_item
*temp_proto_item
;
622 proto_tree
*temp_proto_tree
;
624 /* The order of these if statements is VERY important, this is the order the values will
625 * appear in the cyclic data */
626 if ( (status_data_set
& STATUS_DATA_SET_AXIS_FAULT
) == STATUS_DATA_SET_AXIS_FAULT
)
628 /* Display the various fault codes from the device */
629 proto_tree_add_item(tree
, hf_cip_fault_type
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
632 proto_tree_add_item(tree
, hf_cip_axis_fault
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
635 proto_tree_add_item(tree
, hf_cip_fault_sub_code
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
638 proto_tree_add_item(tree
, hf_cip_fault_action
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
641 proto_tree_add_item(tree
, hf_cip_fault_time_stamp
, tvb
, offset
+ bytes_used
, 8, ENC_LITTLE_ENDIAN
);
645 if ( (status_data_set
& STATUS_DATA_SET_AXIS_ALARM
) == STATUS_DATA_SET_AXIS_ALARM
)
647 /* Display the various alarm codes from the device */
648 proto_tree_add_item(tree
, hf_cip_alarm_type
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
651 proto_tree_add_item(tree
, hf_cip_axis_alarm
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
654 proto_tree_add_item(tree
, hf_cip_alarm_sub_code
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
657 proto_tree_add_item(tree
, hf_cip_alarm_state
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
660 proto_tree_add_item(tree
, hf_cip_alarm_time_stamp
, tvb
, offset
+ bytes_used
, 8, ENC_LITTLE_ENDIAN
);
664 if ( (status_data_set
& STATUS_DATA_SET_AXIS_STATUS
) == STATUS_DATA_SET_AXIS_STATUS
)
666 /* Display the various axis state values from the device */
667 temp_proto_item
= proto_tree_add_item(tree
, hf_cip_axis_status
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
668 temp_proto_tree
= proto_item_add_subtree( temp_proto_item
, ett_axis_status_set
);
669 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_local_ctrl
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
670 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_alarm
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
671 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_dc_bus
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
672 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_pwr_struct
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
673 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_tracking
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
674 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_pos_lock
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
675 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_vel_lock
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
676 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_vel_standstill
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
677 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_vel_threshold
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
678 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_vel_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
679 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_acc_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
680 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_dec_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
681 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_torque_threshold
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
682 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_torque_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
683 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_cur_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
684 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_therm_limit
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
685 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_feedback_integ
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
686 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_shutdown
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
687 proto_tree_add_item( temp_proto_tree
, hf_cip_axis_sts_in_process
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
690 proto_tree_add_item(tree
, hf_cip_axis_status_mfg
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
694 if ( (status_data_set
& STATUS_DATA_SET_AXIS_IO_STATUS
) == STATUS_DATA_SET_AXIS_IO_STATUS
)
696 proto_tree_add_item(tree
, hf_cip_axis_io_status
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
699 proto_tree_add_item(tree
, hf_cip_axis_io_status_mfg
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
703 if ( (status_data_set
& STATUS_DATA_SET_AXIS_SAFETY
) == STATUS_DATA_SET_AXIS_SAFETY
)
705 proto_tree_add_item(tree
, hf_cip_safety_status
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
713 * Function name: dissect_cntr_cyclic
715 * Purpose: Dissect the cyclic data block of a controller to device format message
717 * Returns: The new offset into the message that follow on dissections should use
718 * as their starting offset
721 dissect_cntr_cyclic(guint32 con_format _U_
, tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
, guint32 instance _U_
)
723 proto_item
*header_item
, *temp_proto_item
;
724 proto_tree
*header_tree
, *temp_proto_tree
;
727 guint32 bytes_used
= 0;
729 /* Create the tree for the entire instance data header */
730 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Cyclic Data Block");
731 header_tree
= proto_item_add_subtree(header_item
, ett_cyclic_data_block
);
733 /* Add the control mode header field to the tree */
734 proto_tree_add_item(header_tree
, hf_cip_motor_cntrl
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
736 /* Add the feedback config header field to the tree */
737 proto_tree_add_item(header_tree
, hf_cip_fdbk_config
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
739 /* Add the axis control field to the tree */
740 proto_tree_add_item(header_tree
, hf_cip_axis_control
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
742 /* Add the control status to the tree */
743 proto_tree_add_item(header_tree
, hf_cip_control_status
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
745 /* Read the command control header field from the packet into memory and determine if the dissector
746 * should be using an LREAL or DINT for position */
747 temp_data
= tvb_get_guint8(tvb
, offset
+ 7);
748 lreal_pos
= ( (temp_data
& COMMAND_CONTROL_POSITION_DATA_TYPE
) == POSITION_DATA_LREAL
);
750 /* Read the command data set header field from the packet into memory */
751 temp_data
= tvb_get_guint8(tvb
, offset
+ 4);
753 /* Create the tree for the command data set header field */
754 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_cmd_data_set
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
755 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_command_data_set
);
756 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_pos_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
757 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_vel_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
758 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_acc_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
759 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_trq_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
760 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_pos_trim_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
761 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_vel_trim_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
762 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_acc_trim_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
763 proto_tree_add_item(temp_proto_tree
, hf_cip_cmd_data_trq_trim_cmd
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
765 /* Display the command data values from the cyclic data payload within the command data set tree, the
766 * cyclic data starts immediately after the interpolation control field in the controller to device
768 bytes_used
+= dissect_cmd_data_set(temp_data
, temp_proto_tree
, tvb
, offset
+ 8 + bytes_used
, lreal_pos
);
770 /* Create the tree for the actual data set header field */
771 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_act_data_set
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
772 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_actual_data_set
);
773 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_pos
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
774 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_vel
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
775 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_acc
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
776 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_trq
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
777 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_crnt
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
778 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_vltg
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
779 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_fqcy
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
781 /* Create the tree for the status data set header field */
782 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_sts_data_set
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
783 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_status_data_set
);
784 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_flt
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
785 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_alrm
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
786 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_sts
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
787 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_iosts
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
788 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_safety
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
790 /* Create the tree for the command control header field */
791 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_command_control
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
792 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_command_control
);
794 /* Display the interpolation control and position format fields */
795 proto_tree_add_item(temp_proto_tree
, hf_cip_intrp
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
796 proto_tree_add_item(temp_proto_tree
, hf_cip_position_data_type
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
798 /* Return the offset to the next byte in the message */
799 return offset
+ 8 + bytes_used
;
803 * Function name: dissect_devce_cyclic
805 * Purpose: Dissect the cyclic data block of a device to controller format message
807 * Returns: The new offset into the message that follow on dissections should use
808 * as their starting offset
811 dissect_devce_cyclic(guint32 con_format _U_
, tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
, guint32 instance _U_
)
813 proto_item
*header_item
, *temp_proto_item
;
814 proto_tree
*header_tree
, *temp_proto_tree
;
816 guint32 bytes_used
= 0;
818 /* Create the tree for the entire instance data header */
819 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Cyclic Data Block");
820 header_tree
= proto_item_add_subtree(header_item
, ett_cyclic_data_block
);
822 /* Add the control mode header field to the tree */
823 proto_tree_add_item(header_tree
, hf_cip_motor_cntrl
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
825 /* Add the feedback config header field to the tree */
826 proto_tree_add_item(header_tree
, hf_cip_fdbk_config
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
828 /* Add the axis response field to the tree */
829 proto_tree_add_item(header_tree
, hf_cip_axis_response
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
831 /* Add the axis response status to the tree */
832 proto_tree_add_item(header_tree
, hf_cip_axis_resp_stat
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
834 /* Read the actual data set header field from the packet into memory */
835 temp_data
= tvb_get_guint8(tvb
, offset
+ 5);
837 /* Create the tree for the actual data set header field */
838 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_act_data_set
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
839 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_actual_data_set
);
840 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_pos
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
841 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_vel
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
842 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_acc
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
843 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_trq
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
844 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_crnt
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
845 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_vltg
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
846 proto_tree_add_item(temp_proto_tree
, hf_cip_act_data_fqcy
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
848 /* Display the actual data values from the cyclic data payload within the command data set tree, the
849 * cyclic data starts immediately after the interpolation control field in the controller to device
850 * direction and the actual data starts immediately after the cyclic data */
851 bytes_used
+= dissect_act_data_set(temp_data
, temp_proto_tree
, tvb
, offset
+ 8 + bytes_used
);
853 /* Read the status data set header field from the packet into memory */
854 temp_data
= tvb_get_guint8(tvb
, offset
+ 6);
856 /* Create the tree for the status data set header field */
857 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_sts_data_set
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
858 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_status_data_set
);
859 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_flt
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
860 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_alrm
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
861 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_sts
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
862 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_iosts
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
863 proto_tree_add_item(temp_proto_tree
, hf_cip_sts_safety
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
865 /* Display the status data values from the cyclic data payload within the status data set tree, the
866 * cyclic data starts immediately after the axis state field in the device to controller
867 * direction and the status data starts immediately after the cyclic data */
868 bytes_used
+= dissect_status_data_set(temp_data
, temp_proto_tree
, tvb
, offset
+ 8 + bytes_used
);
870 /* Display the axis state control field */
871 proto_tree_add_item(header_tree
, hf_cip_axis_state
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
873 /* Return the offset to the next byte in the message */
874 return offset
+ 8 + bytes_used
;
878 * Function name: dissect_cyclic_wt
880 * Purpose: Dissect the cyclic write data block in a controller to device message
882 * Returns: The new offset into the message that follow on dissections should use
883 * as their starting offset
886 dissect_cyclic_wt(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
888 proto_item
*header_item
;
889 proto_tree
*header_tree
;
891 /* Create the tree for the entire cyclic write data block */
892 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Cyclic Write Data Block");
893 header_tree
= proto_item_add_subtree(header_item
, ett_cyclic_rd_wt
);
895 /* Display the cyclic write block id value */
896 proto_tree_add_item(header_tree
, hf_cip_cyclic_write_blk
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
898 /* Display the cyclic read block id value */
899 proto_tree_add_item(header_tree
, hf_cip_cyclic_read_blk
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
901 /* Display the remainder of the cyclic write data if there is any */
902 if ( (size
- 4) > 0 )
904 proto_tree_add_item(header_tree
, hf_cip_cyclic_wrt_data
, tvb
, offset
+ 4, size
- 4, ENC_NA
);
907 return offset
+ size
;
911 * Function name: dissect_cyclic_rd
913 * Purpose: Dissect the cyclic read data block in a device to controller message
915 * Returns: The new offset into the message that follow on dissections should use
916 * as their starting offset
919 dissect_cyclic_rd(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
921 proto_item
*header_item
;
922 proto_tree
*header_tree
;
924 /* Create the tree for the entire cyclic write data block */
925 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Cyclic Read Data Block");
926 header_tree
= proto_item_add_subtree(header_item
, ett_cyclic_rd_wt
);
928 /* Display the cyclic write block id value */
929 proto_tree_add_item(header_tree
, hf_cip_cyclic_write_blk
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
931 /* Display the cyclic write status value */
932 proto_tree_add_item(header_tree
, hf_cip_cyclic_write_sts
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
934 /* Display the cyclic read block id value */
935 proto_tree_add_item(header_tree
, hf_cip_cyclic_read_blk
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
937 /* Display the cyclic read status value */
938 proto_tree_add_item(header_tree
, hf_cip_cyclic_read_sts
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
940 /* Display the remainder of the cyclic read data if there is any*/
941 if ( (size
- 4) > 0 )
943 proto_tree_add_item(header_tree
, hf_cip_cyclic_rd_data
, tvb
, offset
+ 4, size
- 4, ENC_NA
);
946 return offset
+ size
;
950 * Function name: dissect_cntr_event
952 * Purpose: Dissect the event data block in a controller to device message
954 * Returns: The new offset into the message that follow on dissections should use
955 * as their starting offset
958 dissect_cntr_event(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
960 proto_item
*header_item
, *temp_proto_item
;
961 proto_tree
*header_tree
, *temp_proto_tree
;
963 guint32 acks
, cur_ack
;
964 guint32 bytes_used
= 0;
966 /* Create the tree for the entire cyclic write data block */
967 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Event Data Block");
968 header_tree
= proto_item_add_subtree(header_item
, ett_event
);
970 /* Read the event checking control header field from the packet into memory */
971 temp_data
= tvb_get_letohl(tvb
, offset
);
973 /* Create the tree for the event checking control header field */
974 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_event_checking
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
975 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_event_check_ctrl
);
977 /* Add the individual elements of the event checking control */
978 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg1_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
979 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg1_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
980 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg2_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
981 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg2_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
982 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg1_posrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
983 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg1_negrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
984 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg2_posrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
985 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_reg2_negrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
986 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_marker_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
987 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_marker_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
988 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
989 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
990 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_pp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
991 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_pm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
992 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_mp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
993 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_home_mm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
994 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_ctrl_acks
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
995 /* The dissector will indicate if the protocol is requesting an extended event format but will not dissect it,
996 * to date no products actually support this format */
997 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_extend_format
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
999 /* The event checking control value is 4 bytes long */
1002 /* The final 4 bits of the event checking control value are the number of acknowledgements in the message */
1003 acks
= (temp_data
>> 28) & 0x0F;
1005 /* Each acknowledgement contains and id and a status value */
1006 for (cur_ack
= 0; cur_ack
< acks
; cur_ack
++)
1008 /* Display the current acknowledgement id */
1009 proto_tree_add_item(header_tree
, hf_cip_event_ack
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
1012 /* Display the current event status */
1013 proto_tree_add_item(header_tree
, hf_cip_evnt_sts_stat
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
1017 return offset
+ size
;
1021 * Function name: dissect_devce_event
1023 * Purpose: Dissect the event data block in a device to controller message
1025 * Returns: The new offset into the message that follow on dissections should use
1026 * as their starting offset
1029 dissect_devce_event(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1031 proto_item
*header_item
, *temp_proto_item
;
1032 proto_tree
*header_tree
, *temp_proto_tree
;
1034 guint64 nots
, cur_not
;
1035 guint32 bytes_used
= 0;
1037 /* Create the tree for the entire cyclic write data block */
1038 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Event Data Block");
1039 header_tree
= proto_item_add_subtree(header_item
, ett_event
);
1041 /* Read the event checking control header field from the packet into memory */
1042 temp_data
= tvb_get_letohl(tvb
, offset
);
1044 /* Create the tree for the event checking control header field */
1045 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_event_status
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1046 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_event_check_sts
);
1048 /* Add the individual elements of the event checking control */
1049 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg1_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1050 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg1_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1051 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg2_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1052 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg2_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1053 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg1_posrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1054 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg1_negrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1055 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg2_posrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1056 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_reg2_negrearm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1057 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_marker_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1058 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_marker_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1059 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1060 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_neg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1061 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_pp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1062 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_pm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1063 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_mp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1064 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_home_mm
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1065 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_sts_nfs
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1066 /* The dissector will indicate if the protocol is requesting an extended event format but will not dissect it,
1067 * to date no products actually support this format */
1068 proto_tree_add_item(temp_proto_tree
, hf_cip_evnt_extend_format
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1070 /* The event status control value is 4 bytes long */
1073 /* The final 4 bits of the event status control value are the number of notifications in the message */
1074 nots
= (temp_data
>> 28) & 0x0F;
1076 /* Each notification contains and id, status value, event type, position and time stamp */
1077 for (cur_not
= 0; cur_not
< nots
; cur_not
++)
1079 /* Display the current event id */
1080 proto_tree_add_item(header_tree
, hf_cip_event_id
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
1083 /* Display the current event status */
1084 proto_tree_add_item(header_tree
, hf_cip_evnt_sts_stat
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
1087 /* Display the current event type */
1088 proto_tree_add_item(header_tree
, hf_cip_evnt_type
, tvb
, offset
+ bytes_used
, 1, ENC_LITTLE_ENDIAN
);
1089 bytes_used
+= 2; /* Increment by 2 to jump the reserved byte */
1091 /* Display the event position value */
1092 proto_tree_add_item(header_tree
, hf_cip_event_pos
, tvb
, offset
+ bytes_used
, 4, ENC_LITTLE_ENDIAN
);
1095 /* Display the event time stamp value */
1096 proto_tree_add_item(header_tree
, hf_cip_event_ts
, tvb
, offset
+ bytes_used
, 8, ENC_LITTLE_ENDIAN
);
1100 return size
+ offset
;
1104 * Function name: dissect_get_axis_attr_list_request
1106 * Purpose: Dissect the get axis attribute list service request
1111 dissect_get_axis_attr_list_request (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1113 proto_item
*header_item
, *attr_item
;
1114 proto_tree
*header_tree
, *attr_tree
;
1115 guint16 attribute
, attribute_cnt
;
1116 guint32 local_offset
;
1117 guint8 increment_size
, dimension
;
1119 /* Create the tree for the get axis attribute list request */
1120 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Get Axis Attribute List Request");
1121 header_tree
= proto_item_add_subtree(header_item
, ett_get_axis_attribute
);
1123 /* Read the number of attributes that are contained within the request */
1124 attribute_cnt
= tvb_get_letohs(tvb
, offset
);
1125 proto_tree_add_item(header_tree
, hf_get_axis_attr_list_attribute_cnt
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1127 /* Start the attribute loop at the beginning of the first attribute in the list */
1128 local_offset
= offset
+ 4;
1130 /* For each attribute display the associated fields */
1131 for (attribute
= 0; attribute
< attribute_cnt
; attribute
++)
1133 /* At a minimum the local offset needs will need to be incremented by 4 bytes to reach the next attribute */
1136 /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
1137 * properly displaying of the attribute is possible */
1138 dimension
= tvb_get_guint8(tvb
, local_offset
+ 2);
1140 /* Create the tree for this attribute within the request */
1141 attr_item
= proto_tree_add_item(header_tree
, hf_get_axis_attr_list_attribute_id
, tvb
, local_offset
, 2, ENC_LITTLE_ENDIAN
);
1142 attr_tree
= proto_item_add_subtree(attr_item
, ett_get_axis_attr_list
);
1144 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_dimension
, tvb
, local_offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1145 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_element_size
, tvb
, local_offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1149 /* Display the start index and start index from the request if this is an array request */
1150 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_start_index
, tvb
, local_offset
+ 4, 2, ENC_LITTLE_ENDIAN
);
1151 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_data_elements
, tvb
, local_offset
+ 6, 2, ENC_LITTLE_ENDIAN
);
1153 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1154 increment_size
+= 4;
1157 /* Move the local offset to the next attribute */
1158 local_offset
+= increment_size
;
1163 * Function name: dissect_set_axis_attr_list_request
1165 * Purpose: Dissect the set axis attribute list service request
1170 dissect_set_axis_attr_list_request (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1172 proto_item
*header_item
, *attr_item
;
1173 proto_tree
*header_tree
, *attr_tree
;
1174 guint16 attribute
, attribute_cnt
, data_elements
;
1175 guint32 local_offset
;
1176 guint32 attribute_size
;
1177 guint8 dimension
, attribute_start
, increment_size
;
1179 /* Create the tree for the set axis attribute list request */
1180 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Set Axis Attribute List Request");
1181 header_tree
= proto_item_add_subtree(header_item
, ett_set_axis_attribute
);
1183 /* Read the number of attributes that are contained within the request */
1184 attribute_cnt
= tvb_get_letohs(tvb
, offset
);
1185 proto_tree_add_item(header_tree
, hf_set_axis_attr_list_attribute_cnt
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1187 /* Start the attribute loop at the beginning of the first attribute in the list */
1188 local_offset
= offset
+ 4;
1190 /* For each attribute display the associated fields */
1191 for (attribute
= 0; attribute
< attribute_cnt
; attribute
++)
1193 /* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
1196 /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
1197 * properly displaying of the attribute is possible */
1198 dimension
= tvb_get_guint8(tvb
, local_offset
+ 2);
1199 attribute_size
= tvb_get_guint8(tvb
, local_offset
+ 3);
1200 attribute_start
= 4;
1204 data_elements
= tvb_get_letohs(tvb
, local_offset
+ 6);
1206 /* Modify the size of the attribute data by the number of elements if the request is an array request */
1207 attribute_size
*= data_elements
;
1209 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1210 increment_size
+= 4;
1211 attribute_start
+= 4;
1214 /* Create the tree for this attribute in the get axis attribute list request */
1215 attr_item
= proto_tree_add_item(header_tree
, hf_set_axis_attr_list_attribute_id
, tvb
, local_offset
, 2, ENC_LITTLE_ENDIAN
);
1216 attr_tree
= proto_item_add_subtree(attr_item
, ett_set_axis_attr_list
);
1218 proto_tree_add_item(attr_tree
, hf_set_axis_attr_list_dimension
, tvb
, local_offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1219 proto_tree_add_item(attr_tree
, hf_set_axis_attr_list_element_size
, tvb
, local_offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1223 /* Display the start index and start index from the request if the request is an array */
1224 proto_tree_add_item(attr_tree
, hf_set_axis_attr_list_start_index
, tvb
, local_offset
+ 4, 2, ENC_LITTLE_ENDIAN
);
1225 proto_tree_add_item(attr_tree
, hf_set_axis_attr_list_data_elements
, tvb
, local_offset
+ 6, 2, ENC_LITTLE_ENDIAN
);
1228 /* Display the value of this attribute */
1229 proto_tree_add_item(attr_tree
, hf_cip_attribute_data
, tvb
, local_offset
+ attribute_start
, attribute_size
, ENC_NA
);
1231 /* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
1232 if (attribute_size
% 4 != 0)
1234 attribute_size
= attribute_size
+ (4 - (attribute_size
% 4));
1237 /* Move the local offset to the next attribute */
1238 local_offset
+= (attribute_size
+ increment_size
);
1243 * Function name: dissect_group_sync_request
1245 * Purpose: Dissect the group sync service request
1250 dissect_group_sync_request (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1252 proto_item
*header_item
;
1253 proto_tree
*header_tree
;
1255 /* Create the tree for the group sync request */
1256 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Group Sync Request");
1257 header_tree
= proto_item_add_subtree(header_item
, ett_group_sync
);
1259 /* Read the grandmaster id from the payload */
1260 proto_tree_add_item(header_tree
, hf_cip_ptp_grandmaster
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1265 * Function name: dissect_cntr_service
1267 * Purpose: Dissect the service data block in a controller to device message
1269 * Returns: The new offset into the message that follow on dissections should use
1270 * as their starting offset
1273 dissect_cntr_service(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1275 proto_item
*header_item
;
1276 proto_tree
*header_tree
;
1279 /* Create the tree for the entire service data block */
1280 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Service Data Block");
1281 header_tree
= proto_item_add_subtree(header_item
, ett_service
);
1283 /* Display the transaction id value */
1284 proto_tree_add_item(header_tree
, hf_cip_svc_transction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1286 /* Display the service code */
1287 service
= tvb_get_guint8(tvb
, offset
+ 1);
1288 proto_tree_add_item(header_tree
, hf_cip_svc_code
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
1290 /* If the service is a set axis, get axis attribute or group sync request dissect it as well */
1293 case SC_GET_AXIS_ATTRIBUTE_LIST
:
1294 dissect_get_axis_attr_list_request(tvb
, header_tree
, offset
+ 4, size
);
1296 case SC_SET_AXIS_ATTRIBUTE_LIST
:
1297 dissect_set_axis_attr_list_request(tvb
, header_tree
, offset
+ 4, size
);
1300 dissect_group_sync_request(tvb
, header_tree
, offset
+ 4, size
);
1303 /* Display the remainder of the service channel data */
1304 proto_tree_add_item(header_tree
, hf_cip_svc_data
, tvb
, offset
+ 4, size
- 4, ENC_NA
);
1307 return offset
+ size
;
1311 * Function name: dissect_set_axis_attr_list_response
1313 * Purpose: Dissect the set axis attribute list service response
1318 dissect_set_axis_attr_list_response (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1320 proto_item
*header_item
, *attr_item
;
1321 proto_tree
*header_tree
, *attr_tree
;
1322 guint16 attribute
, attribute_cnt
;
1323 guint32 local_offset
;
1325 /* Create the tree for the set axis attribute list response */
1326 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Set Axis Attribute List Response");
1327 header_tree
= proto_item_add_subtree(header_item
, ett_get_axis_attribute
);
1329 /* Read the number of attributes that are contained within the response */
1330 attribute_cnt
= tvb_get_letohs(tvb
, offset
);
1331 proto_tree_add_item(header_tree
, hf_set_axis_attr_list_attribute_cnt
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1333 /* Start the attribute loop at the beginning of the first attribute in the list */
1334 local_offset
= offset
+ 4;
1336 /* For each attribute display the associated fields */
1337 for (attribute
= 0; attribute
< attribute_cnt
; attribute
++)
1339 /* Create the tree for the current attribute in the set axis attribute list response */
1340 attr_item
= proto_tree_add_item(header_tree
, hf_set_axis_attr_list_attribute_id
, tvb
, local_offset
, 2, ENC_LITTLE_ENDIAN
);
1341 attr_tree
= proto_item_add_subtree(attr_item
, ett_get_axis_attr_list
);
1343 /* Add the response status to the tree */
1344 proto_tree_add_item(attr_tree
, hf_cip_svc_set_axis_attr_sts
, tvb
, local_offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1346 /* Move the local offset to the next attribute */
1352 * Function name: dissect_get_axis_attr_list_response
1354 * Purpose: Dissect the get axis attribute list service response
1359 dissect_get_axis_attr_list_response (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1361 proto_item
*header_item
, *attr_item
;
1362 proto_tree
*header_tree
, *attr_tree
;
1363 guint16 attribute
, attribute_cnt
, data_elements
;
1364 guint32 attribute_size
;
1365 guint8 dimension
, attribute_start
, increment_size
;
1366 guint32 local_offset
;
1368 /* Create the tree for the get axis attribute list response */
1369 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Get Axis Attribute List Response");
1370 header_tree
= proto_item_add_subtree(header_item
, ett_get_axis_attribute
);
1372 /* Read the number of attributes that are contained within the request */
1373 attribute_cnt
= tvb_get_letohs(tvb
, offset
);
1374 proto_tree_add_item(header_tree
, hf_get_axis_attr_list_attribute_cnt
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1376 /* Start the attribute loop at the beginning of the first attribute in the list */
1377 local_offset
= offset
+ 4;
1379 /* For each attribute display the associated fields */
1380 for (attribute
= 0; attribute
< attribute_cnt
; attribute
++)
1382 /* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
1385 /* Pull the fields for this attribute from the payload, all fields are need to make some calculations before
1386 * properly displaying of the attribute is possible */
1387 dimension
= tvb_get_guint8(tvb
, local_offset
+ 2);
1388 attribute_size
= tvb_get_guint8(tvb
, local_offset
+ 3);
1389 attribute_start
= 4;
1393 data_elements
= tvb_get_letohs(tvb
, local_offset
+ 6);
1395 /* Modify the size of the attribute data by the number of elements if the request is an array request */
1396 attribute_size
*= data_elements
;
1398 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1399 increment_size
+= 4;
1400 attribute_start
+= 4;
1403 /* Display the fields associated with the get axis attribute list response */
1404 attr_item
= proto_tree_add_item(header_tree
, hf_get_axis_attr_list_attribute_id
, tvb
, local_offset
, 2, ENC_LITTLE_ENDIAN
);
1405 attr_tree
= proto_item_add_subtree(attr_item
, ett_get_axis_attr_list
);
1407 if (dimension
== 0xFF)
1409 /* Display the element size as an error code if the dimension field indicates an error */
1410 proto_tree_add_item(attr_tree
, hf_cip_svc_get_axis_attr_sts
, tvb
, local_offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1412 /* No attribute data so no attribute size */
1417 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_dimension
, tvb
, local_offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1418 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_element_size
, tvb
, local_offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1422 /* Display the start index and start indexfrom the request */
1423 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_start_index
, tvb
, local_offset
+ 4, 2, ENC_LITTLE_ENDIAN
);
1424 proto_tree_add_item(attr_tree
, hf_get_axis_attr_list_data_elements
, tvb
, local_offset
+ 6, 2, ENC_LITTLE_ENDIAN
);
1427 /* Display the remainder of the service channel data */
1428 proto_tree_add_item(attr_tree
, hf_cip_attribute_data
, tvb
, offset
+ attribute_start
, attribute_size
, ENC_NA
);
1430 /* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
1431 if (attribute_size
% 4 != 0)
1433 attribute_size
= attribute_size
+ (4 - (attribute_size
% 4));
1437 /* Move the local offset to the next attribute */
1438 local_offset
+= (attribute_size
+ increment_size
);
1443 * Function name: dissect_group_sync_response
1445 * Purpose: Dissect the group sync service response
1450 dissect_group_sync_response (tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size _U_
)
1452 proto_tree_add_item(tree
, hf_cip_group_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1456 * Function name: dissect_devce_service
1458 * Purpose: Dissect the service data block in a device to controller message
1460 * Returns: The new offset into the message that follow on dissections should use
1461 * as their starting offset
1464 dissect_devce_service(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint32 size
)
1466 proto_item
*header_item
;
1467 proto_tree
*header_tree
;
1469 /* Create the tree for the entire service data block */
1470 header_item
= proto_tree_add_text(tree
, tvb
, offset
, size
, "Service Data Block");
1471 header_tree
= proto_item_add_subtree(header_item
, ett_service
);
1473 /* Display the transaction id value */
1474 proto_tree_add_item(header_tree
, hf_cip_svc_transction
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1476 /* Display the service code */
1477 proto_tree_add_item(header_tree
, hf_cip_svc_code
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
1479 /* Display the general status code */
1480 proto_tree_add_item(header_tree
, hf_cip_svc_sts
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1482 /* Display the extended status code */
1483 proto_tree_add_item(header_tree
, hf_cip_svc_ext_status
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1485 /* If the service is a set axis, get axis attribute response or group sync dissect it as well */
1486 switch(tvb_get_guint8(tvb
, offset
+ 1))
1488 case SC_GET_AXIS_ATTRIBUTE_LIST
:
1489 dissect_get_axis_attr_list_response(tvb
, header_tree
, offset
+ 4, size
);
1491 case SC_SET_AXIS_ATTRIBUTE_LIST
:
1492 dissect_set_axis_attr_list_response(tvb
, header_tree
, offset
+ 4, size
);
1495 dissect_group_sync_response(tvb
, header_tree
, offset
+ 4, size
);
1498 /* Display the remainder of the service channel data */
1499 proto_tree_add_item(header_tree
, hf_cip_svc_data
, tvb
, offset
+ 4, size
- 4, ENC_NA
);
1502 return offset
+ size
;
1506 * Function name: dissect_var_inst_header
1508 * Purpose: Dissect the instance data header of a variable controller to device or
1509 * device to controller message
1514 dissect_var_inst_header(tvbuff_t
* tvb
, proto_tree
* tree
, guint32 offset
, guint8
* inst_number
, guint32
* cyc_size
,
1515 guint32
* cyc_blk_size
, guint32
* evnt_size
, guint32
* servc_size
)
1518 proto_item
*header_item
;
1519 proto_tree
*header_tree
;
1521 /* Create the tree for the entire instance data header */
1522 *inst_number
= tvb_get_guint8(tvb
, offset
);
1524 header_item
= proto_tree_add_text(tree
, tvb
, offset
, 8, "Instance Data Header - Instance: %d", *inst_number
);
1525 header_tree
= proto_item_add_subtree(header_item
, ett_inst_data_header
);
1527 /* Read the instance number field from the instance data header */
1528 proto_tree_add_item(header_tree
, hf_var_devce_instance
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1530 /* The "size" fields in the instance data block header are all stored as number of 32-bit words the
1531 * block uses since all blocks should pad up to 32-bits so to convert to bytes each is mulitplied by 4 */
1533 /* Read the instance block size field in bytes from the instance data header */
1534 temp_data
= tvb_get_guint8(tvb
, offset
+ 2);
1535 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_instance_block_size
,
1536 tvb
, offset
+ 2, 1, temp_data
, "%d words", temp_data
);
1538 /* Read the cyclic block size field in bytes from the instance data header */
1539 temp_data
= tvb_get_guint8(tvb
, offset
+ 3);
1540 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_cyclic_block_size
,
1541 tvb
, offset
+ 3, 1, temp_data
, "%d words", temp_data
);
1543 /* Read the cyclic command block size field in bytes from the instance data header */
1544 *cyc_size
= (tvb_get_guint8(tvb
, offset
+ 4) * 4);
1545 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_cyclic_data_block_size
,
1546 tvb
, offset
+ 4, 1, (*cyc_size
)/4, "%d words", (*cyc_size
)/4);
1548 /* Read the cyclic write block size field in bytes from the instance data header */
1549 *cyc_blk_size
= (tvb_get_guint8(tvb
, offset
+ 5) * 4);
1550 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_cyclic_rw_block_size
,
1551 tvb
, offset
+ 5, 1, (*cyc_blk_size
)/4, "%d words", (*cyc_blk_size
)/4);
1553 /* Read the event block size in bytes from the instance data header */
1554 *evnt_size
= (tvb_get_guint8(tvb
, offset
+ 6) * 4);
1555 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_event_block_size
,
1556 tvb
, offset
+ 6, 1, (*evnt_size
)/4, "%d words", (*evnt_size
)/4);
1558 /* Read the service block size in bytes from the instance data header */
1559 *servc_size
= (tvb_get_guint8(tvb
, offset
+ 7) * 4);
1560 proto_tree_add_uint_format_value(header_tree
, hf_var_devce_service_block_size
,
1561 tvb
, offset
+ 7, 1, (*servc_size
)/4, "%d words", (*servc_size
)/4);
1565 * Function name: dissect_var_cont_conn_header
1567 * Purpose: Dissect the connection header of a variable controller to device message
1569 * Returns: Offset to the start of the instance data block
1572 dissect_var_cont_conn_header(tvbuff_t
* tvb
, proto_tree
* tree
, guint32
* inst_count
, guint32 offset
)
1574 guint32 header_size
;
1576 proto_item
*header_item
, *temp_proto_item
;
1577 proto_tree
*header_tree
, *temp_proto_tree
;
1579 /* Calculate the header size, start with the basic header size */
1582 temp_data
= tvb_get_guint8(tvb
, offset
+ 7);
1584 /* Check the time data set field for enabled bits. If either update period or
1585 * update time stamp fields are set, bump the header size by the appropriate size */
1586 if ( (temp_data
& TIME_DATA_SET_TIME_STAMP
) == TIME_DATA_SET_TIME_STAMP
)
1590 if ( (temp_data
& TIME_DATA_SET_TIME_OFFSET
) == TIME_DATA_SET_TIME_OFFSET
)
1595 /* Create the tree for the entire connection header */
1596 header_item
= proto_tree_add_text(tree
, tvb
, offset
, header_size
, "Connection Header");
1597 header_tree
= proto_item_add_subtree(header_item
, ett_cont_dev_header
);
1599 /* Add the connection header fields that are common to all types of messages */
1600 proto_tree_add_item(header_tree
, hf_cip_format
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1601 proto_tree_add_item(header_tree
, hf_cip_revision
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
1602 proto_tree_add_item(header_tree
, hf_cip_updateid
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1604 /* Create the tree for the node control header field */
1605 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_node_control
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1606 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_node_control
);
1608 /* Add the individual data elements to the node control tree */
1609 proto_tree_add_item(temp_proto_tree
, hf_cip_node_control_remote
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1610 proto_tree_add_item(temp_proto_tree
, hf_cip_node_control_sync
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1611 proto_tree_add_item(temp_proto_tree
, hf_cip_node_data_valid
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1612 proto_tree_add_item(temp_proto_tree
, hf_cip_node_fault_reset
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1614 /* Read the instance count field from the packet into memory, this gets passed back out of the method */
1615 *inst_count
= tvb_get_guint8(tvb
, offset
+ 4);
1617 /* Add the instance count and last update id to the connection header tree */
1618 proto_tree_add_item(header_tree
, hf_cip_instance_cnt
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
1619 proto_tree_add_item(header_tree
, hf_cip_last_update
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
1621 /* Read the time data set from the packet into memory */
1622 temp_data
= tvb_get_guint8(tvb
, offset
+ 7);
1624 /* Create the tree for the time data set field */
1625 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_time_data_set
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1626 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_time_data_set
);
1628 /* Add the individual data elements to the time data set header field */
1629 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_stamp
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1630 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_offset
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1631 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_diag
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1632 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_time_diag
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1634 /* Move the offset to the byte just beyond the time data set field */
1635 offset
= (offset
+ 7 + 1);
1637 /* Add the time values if they are present in the time data set header field */
1638 if ( (temp_data
& TIME_DATA_SET_TIME_STAMP
) == TIME_DATA_SET_TIME_STAMP
)
1640 proto_tree_add_item(header_tree
, hf_cip_cont_time_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1641 offset
= (offset
+ 8);
1644 if ( (temp_data
& TIME_DATA_SET_TIME_OFFSET
) == TIME_DATA_SET_TIME_OFFSET
)
1646 proto_tree_add_item(header_tree
, hf_cip_cont_time_offset
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1647 offset
= (offset
+ 8);
1650 /* Return the number of bytes used so it can be used as an offset in the following dissections */
1655 * Function name: dissect_var_devce_conn_header
1657 * Purpose: Dissect the connection header of a variable device to controller message
1659 * Returns: Offset to the start of the instance data block
1662 dissect_var_devce_conn_header(tvbuff_t
* tvb
, proto_tree
* tree
, guint32
* inst_count
, guint32 offset
)
1664 guint32 header_size
;
1666 proto_item
*header_item
, *temp_proto_item
;
1667 proto_tree
*header_tree
, *temp_proto_tree
;
1669 /* Calculate the header size, start with the basic header size */
1672 temp_data
= tvb_get_guint8(tvb
, offset
+ 7);
1673 if ( (temp_data
& TIME_DATA_SET_TIME_STAMP
) == TIME_DATA_SET_TIME_STAMP
)
1677 if ( (temp_data
& TIME_DATA_SET_TIME_OFFSET
) == TIME_DATA_SET_TIME_OFFSET
)
1681 if ( (temp_data
& TIME_DATA_SET_UPDATE_DIAGNOSTICS
) == TIME_DATA_SET_UPDATE_DIAGNOSTICS
)
1685 if ( (temp_data
& TIME_DATA_SET_TIME_DIAGNOSTICS
) == TIME_DATA_SET_TIME_DIAGNOSTICS
)
1690 /* Create the tree for the entire connection header */
1691 header_item
= proto_tree_add_text(tree
, tvb
, offset
, header_size
, "Connection Header");
1692 header_tree
= proto_item_add_subtree(header_item
, ett_cont_dev_header
);
1694 /* Add the connection header fields that are common to all types of messages */
1695 proto_tree_add_item(header_tree
, hf_cip_format
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1696 proto_tree_add_item(header_tree
, hf_cip_revision
, tvb
, offset
+ 1, 1, ENC_LITTLE_ENDIAN
);
1697 proto_tree_add_item(header_tree
, hf_cip_updateid
, tvb
, offset
+ 2, 1, ENC_LITTLE_ENDIAN
);
1699 /* Create the tree for the node status header field */
1700 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_node_status
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1701 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_node_status
);
1703 /* Add the individual data elements to the node control tree */
1704 proto_tree_add_item(temp_proto_tree
, hf_cip_node_control_remote
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1705 proto_tree_add_item(temp_proto_tree
, hf_cip_node_control_sync
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1706 proto_tree_add_item(temp_proto_tree
, hf_cip_node_data_valid
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1707 proto_tree_add_item(temp_proto_tree
, hf_cip_node_device_faulted
, tvb
, offset
+ 3, 1, ENC_LITTLE_ENDIAN
);
1709 /* Read the instance count field from the packet into memory, this gets passed back out of the method */
1710 *inst_count
= tvb_get_guint8(tvb
, offset
+ 4);
1712 /* Add the instance count to the connection header tree */
1713 proto_tree_add_item(header_tree
, hf_cip_instance_cnt
, tvb
, offset
+ 4, 1, ENC_LITTLE_ENDIAN
);
1715 /* The device to controller header contains the node alarms and node faults fields as well. */
1716 proto_tree_add_item(header_tree
, hf_cip_node_fltalarms
, tvb
, offset
+ 5, 1, ENC_LITTLE_ENDIAN
);
1718 /* Add the last update id to the connection header tree */
1719 proto_tree_add_item(header_tree
, hf_cip_last_update
, tvb
, offset
+ 6, 1, ENC_LITTLE_ENDIAN
);
1721 /* Read the time data set from the packet into memory */
1722 temp_data
= tvb_get_guint8(tvb
, offset
+ 7);
1724 /* Create the tree for the time data set field */
1725 temp_proto_item
= proto_tree_add_item(header_tree
, hf_cip_time_data_set
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1726 temp_proto_tree
= proto_item_add_subtree(temp_proto_item
, ett_time_data_set
);
1728 /* Add the individual data elements to the time data set header field */
1729 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_stamp
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1730 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_offset
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1731 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_diag
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1732 proto_tree_add_item(temp_proto_tree
, hf_cip_time_data_time_diag
, tvb
, offset
+ 7, 1, ENC_LITTLE_ENDIAN
);
1734 /* Move the offset to the byte just beyond the time data set field */
1735 offset
= (offset
+ 7 + 1);
1737 /* Add the time values if they are present in the time data set header field */
1738 if ( (temp_data
& TIME_DATA_SET_TIME_STAMP
) == TIME_DATA_SET_TIME_STAMP
)
1740 proto_tree_add_item(header_tree
, hf_cip_devc_time_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1741 offset
= (offset
+ 8);
1744 if ( (temp_data
& TIME_DATA_SET_TIME_OFFSET
) == TIME_DATA_SET_TIME_OFFSET
)
1746 proto_tree_add_item(header_tree
, hf_cip_devc_time_offset
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1747 offset
= (offset
+ 8);
1750 if ( (temp_data
& TIME_DATA_SET_UPDATE_DIAGNOSTICS
) == TIME_DATA_SET_UPDATE_DIAGNOSTICS
)
1752 /* If the time diagnostic bit is set then the header contains the count of lost updates, late updates, data
1753 * received time stamp and data transmit time stamp */
1754 proto_tree_add_item(header_tree
, hf_cip_lost_update
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1755 offset
= (offset
+ 1);
1757 /* Add the reserved bytes to the offset after adding the late updates to the display */
1758 proto_tree_add_item(header_tree
, hf_cip_late_update
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1759 offset
= (offset
+ 3);
1762 if ( (temp_data
& TIME_DATA_SET_TIME_DIAGNOSTICS
) == TIME_DATA_SET_TIME_DIAGNOSTICS
)
1764 proto_tree_add_item(header_tree
, hf_cip_data_rx_time_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1767 proto_tree_add_item(header_tree
, hf_cip_data_tx_time_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1771 /* Return the number of bytes used so it can be used as an offset in the following dissections */
1777 * Function name: dissect_cipmotion
1779 * Purpose: Perform the top level dissection of the CIP Motion datagram, it is called by
1780 * Wireshark when the dissection rule registered in proto_reg_handoff_cipmotion is fired
1785 dissect_cipmotion(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
1788 /* guint32 seq_number; */
1790 proto_item
*proto_item_top
;
1791 proto_tree
*proto_tree_top
;
1794 /* Pull the CIP class 1 sequence number from the incoming message */
1795 /* seq_number = tvb_get_letohs(tvb, offset); */
1796 offset
= (offset
+ 2);
1798 /* Pull the actual values for the connection format and update id from the
1799 * incoming message to be used in the column info */
1800 con_format
= tvb_get_guint8(tvb
, offset
);
1801 update_id
= tvb_get_guint8(tvb
, offset
+ 2);
1803 /* Make entries in Protocol column and Info column on summary display */
1804 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "Motion");
1806 /* Add connection format and update number to the info column */
1807 col_add_fstr( pinfo
->cinfo
, COL_INFO
, "%s, Update Id: %d",
1808 val_to_str(con_format
, cip_con_format_vals
, "Unknown connection format (%x)"), update_id
);
1810 /* If tree is not NULL then Wireshark is requesting that the dissection
1811 * panel be updated with the dissected packet, if tree is NULL then only
1812 * the summary protocol and info columns need to be updated */
1815 /* Create display subtree for the protocol by creating an item and then
1816 * creating a subtree from the item, the subtree must have been registered
1817 * in proto_register_cipmotion already */
1818 proto_item_top
= proto_tree_add_item( tree
, proto_cipmotion
, tvb
, 0, -1, ENC_NA
);
1819 proto_tree_top
= proto_item_add_subtree( proto_item_top
, ett_cipmotion
);
1821 /* Add the CIP class 1 sequence number to the tree */
1822 proto_tree_add_item( proto_tree_top
, hf_cip_class1_seqnum
, tvb
, 0, 2, ENC_LITTLE_ENDIAN
);
1824 /* Attempt to classify the incoming header */
1825 if (( con_format
== FORMAT_VAR_CONTROL_TO_DEVICE
) ||
1826 ( con_format
== FORMAT_VAR_DEVICE_TO_CONTROL
))
1828 /* Sizes of the individual channels within the connection */
1829 guint32 cyc_size
, cyc_blk_size
, evnt_size
, servc_size
;
1830 guint32 inst_count
= 0, inst
;
1832 /* Dissect the header fields */
1835 case FORMAT_VAR_CONTROL_TO_DEVICE
:
1836 offset
= dissect_var_cont_conn_header(tvb
, proto_tree_top
, &inst_count
, offset
);
1838 case FORMAT_VAR_DEVICE_TO_CONTROL
:
1839 offset
= dissect_var_devce_conn_header(tvb
, proto_tree_top
, &inst_count
, offset
);
1843 /* Repeat the following dissections for each instance within the payload */
1844 for( inst
= 0; inst
< inst_count
; inst
++ )
1846 /* Actual instance number from header field */
1849 /* Dissect the instance data header */
1850 dissect_var_inst_header( tvb
, proto_tree_top
, offset
, &instance
,
1851 &cyc_size
, &cyc_blk_size
, &evnt_size
, &servc_size
);
1853 /* Increment the offset to just beyond the instance header */
1856 /* Dissect the cyclic command (actual) data if any exists */
1857 /* Dissect the cyclic write (read) data if any exists */
1858 /* Dissect the event data block if there is any event data */
1861 case FORMAT_VAR_CONTROL_TO_DEVICE
:
1863 offset
= dissect_cntr_cyclic( con_format
, tvb
, proto_tree_top
, offset
, cyc_size
, instance
);
1864 if ( cyc_blk_size
> 0 )
1865 offset
= dissect_cyclic_wt(tvb
, proto_tree_top
, offset
, cyc_blk_size
);
1866 if ( evnt_size
> 0 )
1867 offset
= dissect_cntr_event(tvb
, proto_tree_top
, offset
, evnt_size
);
1868 if ( servc_size
> 0 )
1869 offset
= dissect_cntr_service(tvb
, proto_tree_top
, offset
, servc_size
);
1871 case FORMAT_VAR_DEVICE_TO_CONTROL
:
1873 offset
= dissect_devce_cyclic( con_format
, tvb
, proto_tree_top
, offset
, cyc_size
, instance
);
1874 if ( cyc_blk_size
> 0 )
1875 offset
= dissect_cyclic_rd( tvb
, proto_tree_top
, offset
, cyc_blk_size
);
1876 if ( evnt_size
> 0 )
1877 offset
= dissect_devce_event(tvb
, proto_tree_top
, offset
, evnt_size
);
1878 if ( servc_size
> 0 )
1879 offset
= dissect_devce_service(tvb
, proto_tree_top
, offset
, servc_size
);
1883 } /* End of instance for( ) loop */
1889 * Function name: proto_register_cipmotion
1891 * Purpose: Register the protocol with Wireshark, a script will add this protocol
1892 * to the list of protocols during the build process. This function is where the
1893 * header fields and subtree identifiers are registered.
1898 proto_register_cipmotion(void)
1900 /* This is a list of header fields that can be used in the dissection or
1901 * to use in a filter expression */
1902 static hf_register_info hf
[] =
1904 /* Connection format header field, the first byte in the message which
1905 * determines if the message is fixed or variable, controller to device,
1906 * device to controller, etc. */
1908 { "Connection Format", "cipm.format",
1909 FT_UINT8
, BASE_DEC
, VALS(cip_con_format_vals
), 0,
1910 "Message connection format", HFILL
}
1913 /* Connection format revision header field */
1915 { "Format Revision", "cipm.revision",
1916 FT_UINT8
, BASE_DEC
, NULL
, 0,
1917 "Message format revision", HFILL
}
1920 { &hf_cip_class1_seqnum
,
1921 { "CIP Class 1 Sequence Number", "cipm.class1seqnum",
1922 FT_UINT16
, BASE_DEC
, NULL
, 0,
1926 { "Update Id", "cipm.updateid",
1927 FT_UINT8
, BASE_DEC
, NULL
, 0,
1928 "Cyclic Transaction Number", HFILL
}
1930 { &hf_cip_instance_cnt
,
1931 { "Instance Count", "cipm.instancecount",
1932 FT_UINT8
, BASE_DEC
, NULL
, 0,
1935 { &hf_cip_last_update
,
1936 { "Last Update Id", "cipm.lastupdate",
1937 FT_UINT8
, BASE_DEC
, NULL
, 0,
1940 { &hf_cip_node_status
,
1941 { "Node Status", "cipm.nodestatus",
1942 FT_UINT8
, BASE_HEX
, NULL
, 0,
1945 { &hf_cip_node_control
,
1946 { "Node Control", "cipm.nodecontrol",
1947 FT_UINT8
, BASE_HEX
, NULL
, 0,
1950 { &hf_cip_node_control_remote
,
1951 { "Remote Control", "cipm.remote",
1952 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), 0x01,
1953 "Node Control: Remote Control", HFILL
}
1955 { &hf_cip_node_control_sync
,
1956 { "Sync Control", "cipm.sync",
1957 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), 0x02,
1958 "Node Control: Synchronous Operation", HFILL
}
1960 { &hf_cip_node_data_valid
,
1961 { "Data Valid", "cipm.valid",
1962 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), 0x04,
1963 "Node Control: Data Valid", HFILL
}
1965 { &hf_cip_node_fault_reset
,
1966 { "Fault Reset", "cipm.fltrst",
1967 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), 0x08,
1968 "Node Control: Device Fault Reset", HFILL
}
1970 { &hf_cip_node_device_faulted
,
1971 { "Faulted", "cipm.flt",
1972 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), 0x08,
1973 "Node Control: Device Faulted", HFILL
}
1975 { &hf_cip_node_fltalarms
,
1976 { "Node Faults and Alarms", "cipm.fltalarms",
1977 FT_UINT8
, BASE_DEC
, NULL
, 0,
1980 { &hf_cip_time_data_set
,
1981 { "Time Data Set", "cipm.timedataset",
1982 FT_UINT8
, BASE_HEX
, NULL
, 0,
1985 { &hf_cip_time_data_stamp
,
1986 { "Time Stamp", "cipm.time.stamp",
1987 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TIME_DATA_SET_TIME_STAMP
,
1988 "Time Data Set: Time Stamp", HFILL
}
1990 { &hf_cip_time_data_offset
,
1991 { "Time Offset", "cipm.time.offset",
1992 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TIME_DATA_SET_TIME_OFFSET
,
1993 "Time Data Set: Time Offset", HFILL
}
1995 { &hf_cip_time_data_diag
,
1996 { "Time Update Diagnostics", "cipm.time.update",
1997 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TIME_DATA_SET_UPDATE_DIAGNOSTICS
,
1998 "Time Data Set: Time Update Diagnostics", HFILL
}
2000 { &hf_cip_time_data_time_diag
,
2001 { "Time Diagnostics", "cipm.time.diag",
2002 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), TIME_DATA_SET_TIME_DIAGNOSTICS
,
2003 "Time Data Set: Time Diagnostics", HFILL
}
2006 { &hf_cip_cont_time_stamp
,
2007 { "Controller Time Stamp", "cipm.ctrltimestamp",
2008 FT_UINT64
, BASE_DEC
, NULL
, 0,
2009 "Time Data Set: Controller Time Stamp", HFILL
}
2011 { &hf_cip_cont_time_offset
,
2012 { "Controller Time Offset", "cipm.ctrltimeoffser",
2013 FT_UINT64
, BASE_DEC
, NULL
, 0,
2014 "Time Data Set: Controller Time Offset", HFILL
}
2016 { &hf_cip_data_rx_time_stamp
,
2017 { "Data Received Time Stamp", "cipm.rxtimestamp",
2018 FT_UINT64
, BASE_DEC
, NULL
, 0,
2019 "Time Data Set: Data Received Time Stamp", HFILL
}
2021 { &hf_cip_data_tx_time_stamp
,
2022 { "Data Transmit Time Stamp", "cipm.txtimestamp",
2023 FT_UINT64
, BASE_DEC
, NULL
, 0,
2024 "Time Data Set: Data Transmit Time Offset", HFILL
}
2026 { &hf_cip_devc_time_stamp
,
2027 { "Device Time Stamp", "cipm.devctimestamp",
2028 FT_UINT64
, BASE_DEC
, NULL
, 0,
2029 "Time Data Set: Device Time Stamp", HFILL
}
2031 { &hf_cip_devc_time_offset
,
2032 { "Device Time Offset", "cipm.devctimeoffser",
2033 FT_UINT64
, BASE_DEC
, NULL
, 0,
2034 "Time Data Set: Device Time Offset", HFILL
}
2036 { &hf_cip_lost_update
,
2037 { "Lost Updates", "cipm.lostupdates",
2038 FT_UINT8
, BASE_DEC
, NULL
, 0,
2039 "Time Data Set: Lost Updates", HFILL
}
2041 { &hf_cip_late_update
,
2042 { "Lost Updates", "cipm.lateupdates",
2043 FT_UINT8
, BASE_DEC
, NULL
, 0,
2044 "Time Data Set: Late Updates", HFILL
}
2047 { &hf_cip_motor_cntrl
,
2048 { "Control Mode", "cipm.ctrlmode",
2049 FT_UINT8
, BASE_DEC
, VALS(cip_motor_control_vals
), 0,
2050 "Cyclic Data Block: Motor Control Mode", HFILL
}
2052 { &hf_cip_fdbk_config
,
2053 { "Feedback Config", "cipm.fdbkcfg",
2054 FT_UINT8
, BASE_DEC
, VALS(cip_fdbk_config_vals
), 0,
2055 "Cyclic Data Block: Feedback Configuration", HFILL
}
2057 { &hf_cip_axis_control
,
2058 { "Axis Control", "cipm.axisctrl",
2059 FT_UINT8
, BASE_DEC
, VALS(cip_axis_control_vals
), 0,
2060 "Cyclic Data Block: Axis Control", HFILL
}
2062 { &hf_cip_control_status
,
2063 { "Control Status", "cipm.csts",
2064 FT_UINT8
, BASE_DEC
, VALS(cip_control_status_vals
), 0,
2065 "Cyclic Data Block: Axis Control Status", HFILL
}
2067 { &hf_cip_axis_response
,
2068 { "Axis Response", "cipm.axisresp",
2069 FT_UINT8
, BASE_DEC
, VALS(cip_axis_response_vals
), 0,
2070 "Cyclic Data Block: Axis Response", HFILL
}
2072 { &hf_cip_axis_resp_stat
,
2073 { "Response Status", "cipm.respstat",
2074 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &cip_gs_vals_ext
, 0,
2075 "Cyclic Data Block: Axis Response Status", HFILL
}
2077 { &hf_cip_group_sync
,
2078 { "Group Sync Status", "cipm.syncstatus",
2079 FT_UINT8
, BASE_HEX
, VALS(cip_sync_status_vals
), 0,
2082 { &hf_cip_cmd_data_set
,
2083 { "Command Data Set", "cipm.cmdset",
2084 FT_UINT8
, BASE_HEX
, NULL
, 0,
2087 { &hf_cip_act_data_set
,
2088 { "Actual Data Set", "cipm.actset",
2089 FT_UINT8
, BASE_HEX
, NULL
, 0,
2092 { &hf_cip_sts_data_set
,
2093 { "Status Data Set", "cipm.stsset",
2094 FT_UINT8
, BASE_HEX
, NULL
, 0,
2097 { &hf_cip_cmd_data_pos_cmd
,
2098 { "Command Position", "cipm.cmd.pos",
2099 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_POSITION
,
2100 "Command Data Set: Command Position", HFILL
}
2102 { &hf_cip_cmd_data_vel_cmd
,
2103 { "Command Velocity", "cipm.cmd.vel",
2104 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_VELOCITY
,
2105 "Command Data Set: Command Velocity", HFILL
}
2107 { &hf_cip_cmd_data_acc_cmd
,
2108 { "Command Acceleration", "cipm.cmd.acc",
2109 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_ACCELERATION
,
2110 "Command Data Set: Command Acceleration", HFILL
}
2112 { &hf_cip_cmd_data_trq_cmd
,
2113 { "Command Torque", "cipm.cmd.trq",
2114 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_TORQUE
,
2115 "Command Data Set: Command Torque", HFILL
}
2117 { &hf_cip_cmd_data_pos_trim_cmd
,
2118 { "Position Trim", "cipm.cmd.postrm",
2119 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_POSITION_TRIM
,
2120 "Command Data Set: Position Trim", HFILL
}
2122 { &hf_cip_cmd_data_vel_trim_cmd
,
2123 { "Velocity Trim", "cipm.cmd.veltrm",
2124 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_VELOCITY_TRIM
,
2125 "Command Data Set: Velocity Trim", HFILL
}
2127 { &hf_cip_cmd_data_acc_trim_cmd
,
2128 { "Acceleration Trim", "cipm.cmd.acctrm",
2129 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_ACCELERATION_TRIM
,
2130 "Command Data Set: Acceleration Trim", HFILL
}
2132 { &hf_cip_cmd_data_trq_trim_cmd
,
2133 { "Torque Trim", "cipm.cmd.trqtrm",
2134 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), COMMAND_DATA_SET_TORQUE_TRIM
,
2135 "Command Data Set: Torque Trim", HFILL
}
2138 { &hf_cip_act_data_pos
,
2139 { "Actual Position", "cipm.act.pos",
2140 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_POSITION
,
2141 "Acutal Data Set: Actual Position", HFILL
}
2143 { &hf_cip_act_data_vel
,
2144 { "Actual Velocity", "cipm.act.vel",
2145 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_VELOCITY
,
2146 "Actual Data Set: Actual Velocity", HFILL
}
2148 { &hf_cip_act_data_acc
,
2149 { "Actual Acceleration", "cipm.act.acc",
2150 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_ACCELERATION
,
2151 "Actual Data Set: Actual Acceleration", HFILL
}
2153 { &hf_cip_act_data_trq
,
2154 { "Actual Torque", "cipm.act.trq",
2155 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_TORQUE
,
2156 "Actual Data Set: Actual Torque", HFILL
}
2158 { &hf_cip_act_data_crnt
,
2159 { "Actual Current", "cipm.act.crnt",
2160 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_CURRENT
,
2161 "Actual Data Set: Actual Current", HFILL
}
2163 { &hf_cip_act_data_vltg
,
2164 { "Actual Voltage", "cipm.act.vltg",
2165 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_VOLTAGE
,
2166 "Actual Data Set: Actual Voltage", HFILL
}
2168 { &hf_cip_act_data_fqcy
,
2169 { "Actual Frequency", "cipm.act.fqcy",
2170 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), ACTUAL_DATA_SET_FREQUENCY
,
2171 "Actual Data Set: Actual Frequency", HFILL
}
2174 { &hf_cip_axis_fault
,
2175 { "Axis Fault Code", "cipm.fault.code",
2176 FT_UINT8
, BASE_DEC
, NULL
, 0,
2177 "Status Data Set: Fault Code", HFILL
}
2179 { &hf_cip_fault_type
,
2180 { "Axis Fault Type", "cipm.flttype",
2181 FT_UINT8
, BASE_DEC
, NULL
, 0,
2182 "Axis Status: Axis Fault Type", HFILL
}
2184 { &hf_cip_fault_sub_code
,
2185 { "Axis Fault Sub Code", "cipm.fltsubcode",
2186 FT_UINT8
, BASE_DEC
, NULL
, 0,
2187 "Axis Status: Axis Fault Sub Code", HFILL
}
2189 { &hf_cip_fault_action
,
2190 { "Axis Fault Action", "cipm.fltaction",
2191 FT_UINT8
, BASE_DEC
, NULL
, 0,
2192 "Axis Status: Axis Fault Action", HFILL
}
2194 { &hf_cip_fault_time_stamp
,
2195 { "Axis Fault Time Stamp", "cipm.flttimestamp",
2196 FT_UINT64
, BASE_DEC
, NULL
, 0,
2197 "Axis Status: Axis Fault Time Stamp", HFILL
}
2199 { &hf_cip_alarm_type
,
2200 { "Axis Fault Type", "cipm.alarmtype",
2201 FT_UINT8
, BASE_DEC
, NULL
, 0,
2202 "Axis Status: Axis Alarm Type", HFILL
}
2204 { &hf_cip_alarm_sub_code
,
2205 { "Axis Alarm Sub Code", "cipm.alarmsubcode",
2206 FT_UINT8
, BASE_DEC
, NULL
, 0,
2207 "Axis Status: Axis Alarm Sub Code", HFILL
}
2209 { &hf_cip_alarm_state
,
2210 { "Axis Alarm State", "cipm.alarmstate",
2211 FT_UINT8
, BASE_DEC
, NULL
, 0,
2212 "Axis Status: Axis Alarm State", HFILL
}
2214 { &hf_cip_alarm_time_stamp
,
2215 { "Axis Fault Time Stamp", "cipm.alarmtimestamp",
2216 FT_UINT64
, BASE_DEC
, NULL
, 0,
2217 "Axis Status: Axis Alarm Time Stamp", HFILL
}
2219 { &hf_cip_axis_status
,
2220 { "Axis Status", "cipm.axisstatus",
2221 FT_UINT32
, BASE_HEX
, NULL
, 0,
2224 { &hf_cip_axis_status_mfg
,
2225 { "Axis Status Mfg", "cipm.axisstatusmfg",
2226 FT_UINT32
, BASE_HEX
, NULL
, 0,
2227 "Axis Status, Manufacturer Specific", HFILL
}
2229 { &hf_cip_axis_io_status
,
2230 { "Axis I/O Status", "cipm.axisiostatus",
2231 FT_UINT32
, BASE_HEX
, NULL
, 0,
2234 { &hf_cip_axis_io_status_mfg
,
2235 { "Axis I/O Status Mfg", "cipm.axisiostatusmfg",
2236 FT_UINT32
, BASE_HEX
, NULL
, 0,
2237 "Axis I/O Status, Manufacturer Specific", HFILL
}
2239 { &hf_cip_safety_status
,
2240 { "Axis Safety Status", "cipm.safetystatus",
2241 FT_UINT32
, BASE_HEX
, NULL
, 0,
2245 { "Axis Fault Codes", "cipm.sts.flt",
2246 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), STATUS_DATA_SET_AXIS_FAULT
,
2247 "Status Data Set: Axis Fault Codes", HFILL
}
2250 { "Axis Alarm Codes", "cipm.sts.alarm",
2251 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), STATUS_DATA_SET_AXIS_ALARM
,
2252 "Status Data Set: Axis Alarm Codes", HFILL
}
2255 { "Axis Status", "cipm.sts.sts",
2256 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), STATUS_DATA_SET_AXIS_STATUS
,
2257 "Status Data Set: Axis Status", HFILL
}
2259 { &hf_cip_sts_iosts
,
2260 { "Axis I/O Status", "cipm.sts.iosts",
2261 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), STATUS_DATA_SET_AXIS_IO_STATUS
,
2262 "Status Data Set: Axis I/O Status", HFILL
}
2264 { &hf_cip_sts_safety
,
2265 { "Axis Safety Status", "cipm.sts.safety",
2266 FT_BOOLEAN
, 8, TFS(&tfs_true_false
), STATUS_DATA_SET_AXIS_SAFETY
,
2267 "Status Data Set: Axis Safety Status", HFILL
}
2271 { "Interpolation Control", "cipm.intrp",
2272 FT_UINT8
, BASE_DEC
, VALS(cip_interpolation_vals
), COMMAND_CONTROL_TARGET_UPDATE
,
2273 "Cyclic Data Block: Interpolation Control", HFILL
}
2275 { &hf_cip_position_data_type
,
2276 { "Position Data Type", "cipm.posdatatype",
2277 FT_UINT8
, BASE_DEC
, VALS(cip_pos_data_type_vals
), COMMAND_CONTROL_POSITION_DATA_TYPE
,
2278 "Cyclic Data Block: Position Data Type", HFILL
}
2280 { &hf_cip_axis_state
,
2281 { "Axis State", "cipm.axste",
2282 FT_UINT8
, BASE_DEC
, VALS(cip_axis_state_vals
), 0,
2283 "Cyclic Data Block: Axis State", HFILL
}
2285 { &hf_cip_command_control
,
2286 { "Command Control", "cipm.cmdcontrol",
2287 FT_UINT8
, BASE_DEC
, NULL
, 0,
2288 "Cyclic Data Block: Command Control", HFILL
}
2290 { &hf_cip_cyclic_wrt_data
,
2291 { "Write Data", "cipm.writedata",
2292 FT_BYTES
, BASE_NONE
, NULL
, 0,
2293 "Cyclic Write: Data", HFILL
}
2295 { &hf_cip_cyclic_rd_data
,
2296 { "Read Data", "cipm.readdata",
2297 FT_BYTES
, BASE_NONE
, NULL
, 0,
2298 "Cyclic Read: Data", HFILL
}
2300 { &hf_cip_cyclic_write_blk
,
2301 { "Write Block", "cipm.writeblk",
2302 FT_UINT8
, BASE_DEC
, NULL
, 0,
2303 "Cyclic Data Block: Write Block Id", HFILL
}
2305 { &hf_cip_cyclic_read_blk
,
2306 { "Read Block", "cipm.readblk",
2307 FT_UINT8
, BASE_DEC
, NULL
, 0,
2308 "Cyclic Data Block: Read Block Id", HFILL
}
2310 { &hf_cip_cyclic_write_sts
,
2311 { "Write Status", "cipm.writests",
2312 FT_UINT8
, BASE_DEC
, NULL
, 0,
2313 "Cyclic Data Block: Write Status", HFILL
}
2315 { &hf_cip_cyclic_read_sts
,
2316 { "Read Status", "cipm.readsts",
2317 FT_UINT8
, BASE_DEC
, NULL
, 0,
2318 "Cyclic Data Block: Read Status", HFILL
}
2320 { &hf_cip_event_checking
,
2321 { "Event Control", "cipm.evntchkcontrol",
2322 FT_UINT32
, BASE_HEX
, NULL
, 0,
2323 "Event Channel: Event Checking Control", HFILL
}
2325 { &hf_cip_event_ack
,
2326 { "Event Acknowledgement", "cipm.evntack",
2327 FT_UINT8
, BASE_DEC
, NULL
, 0,
2328 "Event Channel: Event Acknowledgement", HFILL
}
2330 { &hf_cip_event_status
,
2331 { "Event Status", "cipm.evntchkstatus",
2332 FT_UINT32
, BASE_HEX
, NULL
, 0,
2333 "Event Channel: Event Checking Status", HFILL
}
2336 { "Event Id", "cipm.evntack",
2337 FT_UINT8
, BASE_DEC
, NULL
, 0,
2338 "Event Channel: Event Id", HFILL
}
2340 { &hf_cip_event_pos
,
2341 { "Event Position", "cipm.evntpos",
2342 FT_INT32
, BASE_DEC
, NULL
, 0,
2343 "Event Channel: Event Position", HFILL
}
2346 { "Event Time Stamp", "cipm.evntimestamp",
2347 FT_UINT64
, BASE_DEC
, NULL
, 0,
2348 "Event Channel: Time Stamp", HFILL
}
2351 { &hf_cip_evnt_ctrl_reg1_pos
,
2352 { "Reg 1 Pos Edge", "cipm.evnt.ctrl.reg1posedge",
2353 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000001,
2354 "Event Checking Control: Reg 1 Pos Edge", HFILL
}
2356 { &hf_cip_evnt_ctrl_reg1_neg
,
2357 { "Reg 1 Neg Edge", "cipm.evnt.ctrl.reg1negedge",
2358 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000002,
2359 "Event Checking Control: Reg 1 Neg Edge", HFILL
}
2361 { &hf_cip_evnt_ctrl_reg2_pos
,
2362 { "Reg 2 Pos Edge", "cipm.evnt.ctrl.reg2posedge",
2363 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000004,
2364 "Event Checking Control: Reg 2 Pos Edge", HFILL
}
2366 { &hf_cip_evnt_ctrl_reg2_neg
,
2367 { "Reg 2 Neg Edge", "cipm.evnt.ctrl.reg2negedge",
2368 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000008,
2369 "Event Checking Control: Reg 2 Neg Edge", HFILL
}
2371 { &hf_cip_evnt_ctrl_reg1_posrearm
,
2372 { "Reg 1 Pos Rearm", "cipm.evnt.ctrl.reg1posrearm",
2373 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000100,
2374 "Event Checking Control: Reg 1 Pos Rearm", HFILL
}
2376 { &hf_cip_evnt_ctrl_reg1_negrearm
,
2377 { "Reg 1 Neg Rearm", "cipm.evnt.ctrl.reg1negrearm",
2378 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000200,
2379 "Event Checking Control: Reg 1 Neg Rearm", HFILL
}
2381 { &hf_cip_evnt_ctrl_reg2_posrearm
,
2382 { "Reg 2 Pos Rearm", "cipm.evnt.ctrl.reg2posrearm",
2383 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000400,
2384 "Event Checking Control: Reg 2 Pos Rearm", HFILL
}
2386 { &hf_cip_evnt_ctrl_reg2_negrearm
,
2387 { "Reg 2 Neg Rearm", "cipm.evnt.ctrl.reg2negrearm",
2388 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000800,
2389 "Event Checking Control: Reg 2 Neg Rearm", HFILL
}
2391 { &hf_cip_evnt_ctrl_marker_pos
,
2392 { "Marker Pos Edge", "cipm.evnt.ctrl.mrkrpos",
2393 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00010000,
2394 "Event Checking Control: Marker Pos Edge", HFILL
}
2396 { &hf_cip_evnt_ctrl_marker_neg
,
2397 { "Marker Neg Edge", "cipm.evnt.ctrl.mrkrneg",
2398 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00020000,
2399 "Event Checking Control: Marker Neg Edge", HFILL
}
2401 { &hf_cip_evnt_ctrl_home_pos
,
2402 { "Home Pos Edge", "cipm.evnt.ctrl.homepos",
2403 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00040000,
2404 "Event Checking Control: Home Pos Edge", HFILL
}
2406 { &hf_cip_evnt_ctrl_home_neg
,
2407 { "Home Neg Edge", "cipm.evnt.ctrl.homeneg",
2408 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00080000,
2409 "Event Checking Control: Home Neg Edge", HFILL
}
2411 { &hf_cip_evnt_ctrl_home_pp
,
2412 { "Home-Switch-Marker Plus Plus", "cipm.evnt.ctrl.homepp",
2413 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00100000,
2414 "Event Checking Control: Home-Switch-Marker Plus Plus", HFILL
}
2416 { &hf_cip_evnt_ctrl_home_pm
,
2417 { "Home-Switch-Marker Plus Minus", "cipm.evnt.ctrl.homepm",
2418 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00200000,
2419 "Event Checking Control: Home-Switch-Marker Plus Minus", HFILL
}
2421 { &hf_cip_evnt_ctrl_home_mp
,
2422 { "Home-Switch-Marker Minus Plus", "cipm.evnt.ctrl.homemp",
2423 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00400000,
2424 "Event Checking Control: Home-Switch-Marker Minus Plus", HFILL
}
2426 { &hf_cip_evnt_ctrl_home_mm
,
2427 { "Home-Switch-Marker Minus Minus", "cipm.evnt.ctrl.homemm",
2428 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00800000,
2429 "Event Checking Control: Home-Switch-Marker Minus Minus", HFILL
}
2431 { &hf_cip_evnt_ctrl_acks
,
2432 { "Event Acknowledge Blocks", "cipm.evnt.ctrl.acks",
2433 FT_UINT32
, BASE_DEC
, NULL
, 0x70000000,
2434 "Event Checking Control: Event Acknowledge Blocks", HFILL
}
2436 { &hf_cip_evnt_extend_format
,
2437 { "Extended Event Format", "cipm.evnt.extend",
2438 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x80000000,
2439 "Event Checking Control: Extended Event Format", HFILL
}
2442 { &hf_cip_evnt_sts_reg1_pos
,
2443 { "Reg 1 Pos Edge", "cipm.evnt.sts.reg1posedge",
2444 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000001,
2445 "Event Checking Status: Reg 1 Pos Edge", HFILL
}
2447 { &hf_cip_evnt_sts_reg1_neg
,
2448 { "Reg 1 Neg Edge", "cipm.evnt.sts.reg1negedge",
2449 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000002,
2450 "Event Checking Status: Reg 1 Neg Edge", HFILL
}
2452 { &hf_cip_evnt_sts_reg2_pos
,
2453 { "Reg 2 Pos Edge", "cipm.evnt.sts.reg2posedge",
2454 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000004,
2455 "Event Checking Status: Reg 2 Pos Edge", HFILL
}
2457 { &hf_cip_evnt_sts_reg2_neg
,
2458 { "Reg 2 Neg Edge", "cipm.evnt.sts.reg2negedge",
2459 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000008,
2460 "Event Checking Status: Reg 2 Neg Edge", HFILL
}
2462 { &hf_cip_evnt_sts_reg1_posrearm
,
2463 { "Reg 1 Pos Rearm", "cipm.evnt.sts.reg1posrearm",
2464 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000100,
2465 "Event Checking Status: Reg 1 Pos Rearm", HFILL
}
2467 { &hf_cip_evnt_sts_reg1_negrearm
,
2468 { "Reg 1 Neg Rearm", "cipm.evnt.sts.reg1negrearm",
2469 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000200,
2470 "Event Checking Status: Reg 1 Neg Rearm", HFILL
}
2472 { &hf_cip_evnt_sts_reg2_posrearm
,
2473 { "Reg 2 Pos Rearm", "cipm.evnt.sts.reg2posrearm",
2474 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000400,
2475 "Event Checking Status: Reg 2 Pos Rearm", HFILL
}
2477 { &hf_cip_evnt_sts_reg2_negrearm
,
2478 { "Reg 2 Neg Rearm", "cipm.evnt.sts.reg2negrearm",
2479 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000800,
2480 "Event Checking Status: Reg 2 Neg Rearm", HFILL
}
2482 { &hf_cip_evnt_sts_marker_pos
,
2483 { "Marker Pos Edge", "cipm.evnt.sts.mrkrpos",
2484 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00010000,
2485 "Event Checking Status: Marker Pos Edge", HFILL
}
2487 { &hf_cip_evnt_sts_marker_neg
,
2488 { "Marker Neg Edge", "cipm.evnt.sts.mrkrneg",
2489 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00020000,
2490 "Event Checking Status: Marker Neg Edge", HFILL
}
2492 { &hf_cip_evnt_sts_home_pos
,
2493 { "Home Pos Edge", "cipm.evnt.sts.homepos",
2494 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00040000,
2495 "Event Checking Status: Home Pos Edge", HFILL
}
2497 { &hf_cip_evnt_sts_home_neg
,
2498 { "Home Neg Edge", "cipm.evnt.sts.homeneg",
2499 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00080000,
2500 "Event Checking Status: Home Neg Edge", HFILL
}
2502 { &hf_cip_evnt_sts_home_pp
,
2503 { "Home-Switch-Marker Plus Plus", "cipm.evnt.sts.homepp",
2504 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00100000,
2505 "Event Checking Status: Home-Switch-Marker Plus Plus", HFILL
}
2507 { &hf_cip_evnt_sts_home_pm
,
2508 { "Home-Switch-Marker Plus Minus", "cipm.evnt.sts.homepm",
2509 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00200000,
2510 "Event Checking Status: Home-Switch-Marker Plus Minus", HFILL
}
2512 { &hf_cip_evnt_sts_home_mp
,
2513 { "Home-Switch-Marker Minus Plus", "cipm.evnt.sts.homemp",
2514 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00400000,
2515 "Event Checking Status: Home-Switch-Marker Minus Plus", HFILL
}
2517 { &hf_cip_evnt_sts_home_mm
,
2518 { "Home-Switch-Marker Minus Minus", "cipm.evnt.sts.homemm",
2519 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00800000,
2520 "Event Checking Status: Home-Switch-Marker Minus Minus", HFILL
}
2522 { &hf_cip_evnt_sts_nfs
,
2523 { "Event Notification Blocks", "cipm.evnt.sts.nfs",
2524 FT_UINT32
, BASE_DEC
, NULL
, 0x70000000,
2525 "Event Checking Status: Event Notification Blocks", HFILL
}
2528 { &hf_cip_evnt_sts_stat
,
2529 { "Event Status", "cipm.evnt.stat",
2530 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &cip_gs_vals_ext
, 0,
2531 "Event Data Block: Event Status", HFILL
}
2533 { &hf_cip_evnt_type
,
2534 { "Event Type", "cipm.evnt.type",
2535 FT_UINT8
, BASE_DEC
, VALS(cip_event_type_vals
), 0,
2536 "Event Data Block: Event Type", HFILL
}
2539 { "Service Code", "cipm.svc.code",
2540 FT_UINT8
, BASE_DEC
, VALS(cip_sc_vals
), 0,
2541 "Service Data Block: Service Code", HFILL
}
2544 { "General Status", "cipm.svc.sts",
2545 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &cip_gs_vals_ext
, 0,
2546 "Service Data Block: General Status", HFILL
}
2548 { &hf_cip_svc_transction
,
2549 { "Transaction Id", "cipm.svc.tranid",
2550 FT_UINT8
, BASE_DEC
, NULL
, 0,
2551 "Service Data Block: Transaction Id", HFILL
}
2553 { &hf_cip_svc_ext_status
,
2554 { "Extended Status", "cipm.svc.extstatus",
2555 FT_UINT8
, BASE_DEC
, NULL
, 0,
2556 "Service Data Block: Extended Status", HFILL
}
2559 { "Service Data", "cipm.svc.data",
2560 FT_BYTES
, BASE_NONE
, NULL
, 0,
2561 "Service Data Block: Data", HFILL
}
2563 { &hf_cip_attribute_data
,
2564 { "Attribute Data", "cipm.attrdata",
2565 FT_BYTES
, BASE_NONE
, NULL
, 0,
2566 "Attribute Service: Data", HFILL
}
2568 { &hf_cip_ptp_grandmaster
,
2569 { "Grandmaster", "cipm.grandmaster",
2570 FT_UINT64
, BASE_HEX
, NULL
, 0,
2571 "Group Sync: Grandmaster Id", HFILL
}
2574 { &hf_cip_svc_get_axis_attr_sts
,
2575 { "Attribute Status", "cipm.getaxisattr.sts",
2576 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &cip_gs_vals_ext
, 0,
2577 "Service Channel: Get Axis Attribute List Response Status", HFILL
}
2579 { &hf_get_axis_attr_list_attribute_cnt
,
2580 { "Number of attributes", "cipm.getaxisattr.cnt",
2581 FT_UINT16
, BASE_DEC
, NULL
, 0,
2582 "Service Channel: Get Axis Attribute List Attribute Count", HFILL
}
2584 { &hf_get_axis_attr_list_attribute_id
,
2585 { "Attribute ID", "cipm.getaxisattr.id",
2586 FT_UINT16
, BASE_DEC
, NULL
, 0,
2587 "Service Channel: Get Axis Attribute List Attribute ID", HFILL
}
2589 { &hf_get_axis_attr_list_dimension
,
2590 { "Dimension", "cipm.getaxisattr.dimension",
2591 FT_UINT8
, BASE_DEC
, NULL
, 0,
2592 "Service Channel: Get Axis Attribute List Dimension", HFILL
}
2594 { &hf_get_axis_attr_list_element_size
,
2595 { "Element size", "cipm.getaxisattr.element_size",
2596 FT_UINT8
, BASE_DEC
, NULL
, 0,
2597 "Service Channel: Get Axis Attribute List Element Size", HFILL
}
2599 { &hf_get_axis_attr_list_start_index
,
2600 { "Start index", "cipm.getaxisattr.start_index",
2601 FT_UINT16
, BASE_DEC
, NULL
, 0,
2602 "Service Channel: Get Axis Attribute List Start index", HFILL
}
2604 { &hf_get_axis_attr_list_data_elements
,
2605 { "Data elements", "cipm.getaxisattr.data_elements",
2606 FT_UINT16
, BASE_DEC
, NULL
, 0,
2607 "Service Channel: Get Axis Attribute List Data elements", HFILL
}
2610 { &hf_cip_svc_set_axis_attr_sts
,
2611 { "Attribute Status", "cipm.setaxisattr.sts",
2612 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &cip_gs_vals_ext
, 0,
2613 "Service Channel: Set Axis Attribute List Response Status", HFILL
}
2615 { &hf_set_axis_attr_list_attribute_cnt
,
2616 { "Number of attributes", "cipm.setaxisattr.cnt",
2617 FT_UINT16
, BASE_DEC
, NULL
, 0,
2618 "Service Channel: Set Axis Attribute List Attribute Count", HFILL
}
2620 { &hf_set_axis_attr_list_attribute_id
,
2621 { "Attribute ID", "cipm.setaxisattr.id",
2622 FT_UINT16
, BASE_DEC
, NULL
, 0,
2623 "Service Channel: Set Axis Attribute List Attribute ID", HFILL
}
2625 { &hf_set_axis_attr_list_dimension
,
2626 { "Dimension", "cipm.setaxisattr.dimension",
2627 FT_UINT8
, BASE_DEC
, NULL
, 0,
2628 "Service Channel: Set Axis Attribute List Dimension", HFILL
}
2630 { &hf_set_axis_attr_list_element_size
,
2631 { "Element size", "cipm.setaxisattr.element_size",
2632 FT_UINT8
, BASE_DEC
, NULL
, 0,
2633 "Service Channel: Set Axis Attribute List Element Size", HFILL
}
2635 { &hf_set_axis_attr_list_start_index
,
2636 { "Start index", "cipm.setaxisattr.start_index",
2637 FT_UINT16
, BASE_DEC
, NULL
, 0,
2638 "Service Channel: Set Axis Attribute List Start index", HFILL
}
2640 { &hf_set_axis_attr_list_data_elements
,
2641 { "Data elements", "cipm.setaxisattr.data_elements",
2642 FT_UINT16
, BASE_DEC
, NULL
, 0,
2643 "Service Channel: Set Axis Attribute List Data elements", HFILL
}
2646 { &hf_var_devce_instance
,
2647 { "Instance Number", "cipm.var_devce.header.instance",
2648 FT_UINT8
, BASE_DEC
, NULL
, 0,
2649 "Variable Device Header: Instance Number", HFILL
}
2651 { &hf_var_devce_instance_block_size
,
2652 { "Instance Block Size", "cipm.var_devce.header.instance_block_size",
2653 FT_UINT8
, BASE_DEC
, NULL
, 0,
2654 "Variable Device Header: Instance Block Size", HFILL
}
2656 { &hf_var_devce_cyclic_block_size
,
2657 { "Cyclic Block Size", "cipm.var_devce.header.cyclic_block_size",
2658 FT_UINT8
, BASE_DEC
, NULL
, 0,
2659 "Variable Device Header: Cyclic Block Size", HFILL
}
2661 { &hf_var_devce_cyclic_data_block_size
,
2662 { "Cyclic Data Block Size", "cipm.var_devce.header.cyclic_data_block_size",
2663 FT_UINT8
, BASE_DEC
, NULL
, 0,
2664 "Variable Device Header: Cyclic Data Block Size", HFILL
}
2666 { &hf_var_devce_cyclic_rw_block_size
,
2667 { "Cyclic Read/Write Block Size", "cipm.var_devce.header.cyclic_rw_block_size",
2668 FT_UINT8
, BASE_DEC
, NULL
, 0,
2669 "Variable Device Header: Cyclic Read/Write Block Size", HFILL
}
2671 { &hf_var_devce_event_block_size
,
2672 { "Event Block Size", "cipm.var_devce.header.event_block_size",
2673 FT_UINT8
, BASE_DEC
, NULL
, 0,
2674 "Variable Device Header: Event Block Size", HFILL
}
2676 { &hf_var_devce_service_block_size
,
2677 { "Service Block Size", "cipm.var_devce.header.service_block_size",
2678 FT_UINT8
, BASE_DEC
, NULL
, 0,
2679 "Variable Device Header: Service Block Size", HFILL
}
2682 { &hf_cip_axis_alarm
,
2683 { "Axis Alarm Code", "cipm.alarm.code",
2684 FT_UINT8
, BASE_DEC
, NULL
, 0,
2685 "Status Data Set: Alarm Code", HFILL
}
2687 { &hf_cip_axis_sts_local_ctrl
,
2688 { "Local Control", "cipm.axis.local",
2689 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000001,
2690 "Axis Status Data Set: Local Contol", HFILL
}
2692 { &hf_cip_axis_sts_alarm
,
2693 { "Alarm", "cipm.axis.alarm",
2694 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000002,
2695 "Axis Status Data Set: Alarm", HFILL
}
2697 { &hf_cip_axis_sts_dc_bus
,
2698 { "DC Bus", "cipm.axis.bus",
2699 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000004,
2700 "Axis Status Data Set: DC Bus", HFILL
}
2702 { &hf_cip_axis_sts_pwr_struct
,
2703 { "Power Struct", "cipm.axis.pwr",
2704 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000008,
2705 "Axis Status Data Set: Power Struct", HFILL
}
2707 { &hf_cip_axis_sts_tracking
,
2708 { "Tracking", "cipm.axis.track",
2709 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000020,
2710 "Axis Status Data Set: Tracking", HFILL
}
2712 { &hf_cip_axis_sts_pos_lock
,
2713 { "Pos Lock", "cipm.axis.poslock",
2714 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000040,
2715 "Axis Status Data Set: Pos Lock", HFILL
}
2717 { &hf_cip_axis_sts_vel_lock
,
2718 { "Vel Lock", "cipm.axis.vellock",
2719 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000080,
2720 "Axis Status Data Set: Vel Lock", HFILL
}
2722 { &hf_cip_axis_sts_vel_standstill
,
2723 { "Standstill", "cipm.axis.nomo",
2724 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000100,
2725 "Axis Status Data Set: Standstill", HFILL
}
2727 { &hf_cip_axis_sts_vel_threshold
,
2728 { "Vel Threshold", "cipm.axis.vthresh",
2729 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000200,
2730 "Axis Status Data Set: Vel Threshold", HFILL
}
2732 { &hf_cip_axis_sts_vel_limit
,
2733 { "Vel Limit", "cipm.axis.vlim",
2734 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000400,
2735 "Axis Status Data Set: Vel Limit", HFILL
}
2737 { &hf_cip_axis_sts_acc_limit
,
2738 { "Acc Limit", "cipm.axis.alim",
2739 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00000800,
2740 "Axis Status Data Set: Acc Limit", HFILL
}
2742 { &hf_cip_axis_sts_dec_limit
,
2743 { "Dec Limit", "cipm.axis.dlim",
2744 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00001000,
2745 "Axis Status Data Set: Dec Limit", HFILL
}
2747 { &hf_cip_axis_sts_torque_threshold
,
2748 { "Torque Threshold", "cipm.axis.tthresh",
2749 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00002000,
2750 "Axis Status Data Set: Torque Threshold", HFILL
}
2752 { &hf_cip_axis_sts_torque_limit
,
2753 { "Torque Limit", "cipm.axis.tlim",
2754 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00004000,
2755 "Axis Status Data Set: Torque Limit", HFILL
}
2757 { &hf_cip_axis_sts_cur_limit
,
2758 { "Current Limit", "cipm.axis.ilim",
2759 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00008000,
2760 "Axis Status Data Set: Current Limit", HFILL
}
2762 { &hf_cip_axis_sts_therm_limit
,
2763 { "Thermal Limit", "cipm.axis.hot",
2764 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00010000,
2765 "Axis Status Data Set: Thermal Limit", HFILL
}
2767 { &hf_cip_axis_sts_feedback_integ
,
2768 { "Feedback Integrity", "cipm.axis.fgood",
2769 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00020000,
2770 "Axis Status Data Set: Feedback Integrity", HFILL
}
2772 { &hf_cip_axis_sts_shutdown
,
2773 { "Shutdown", "cipm.axis.sdwn",
2774 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00040000,
2775 "Axis Status Data Set: Shutdown", HFILL
}
2777 { &hf_cip_axis_sts_in_process
,
2778 { "In Process", "cipm.axis.inp",
2779 FT_BOOLEAN
, 32, TFS(&tfs_true_false
), 0x00080000,
2780 "Axis Status Data Set: In Process", HFILL
}
2784 { "Actual Position", "cipm.actpos",
2785 FT_INT32
, BASE_DEC
, NULL
, 0,
2786 "Cyclic Data Set: Actual Position", HFILL
}
2789 { "Actual Velocity", "cipm.actvel",
2790 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2791 "Cyclic Data Set: Actual Velocity", HFILL
}
2793 { &hf_cip_act_accel
,
2794 { "Actual Acceleration", "cipm.actaccel",
2795 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2796 "Cyclic Data Set: Actual Acceleration", HFILL
}
2799 { "Actual Torque", "cipm.acttrq",
2800 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2801 "Cyclic Data Set: Actual Torque", HFILL
}
2804 { "Actual Current", "cipm.actcrnt",
2805 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2806 "Cyclic Data Set: Actual Current", HFILL
}
2808 { &hf_cip_act_volts
,
2809 { "Actual Volts", "cipm.actvolts",
2810 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2811 "Cyclic Data Set: Actual Volts", HFILL
}
2814 { "Actual Frequency", "cipm.actfreq",
2815 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2816 "Cyclic Data Set: Actual Frequency", HFILL
}
2819 { "Position Command", "cipm.posfcmd",
2820 FT_DOUBLE
, BASE_NONE
, NULL
, 0,
2821 "Cyclic Data Set: Position Command (LREAL)", HFILL
}
2823 { &hf_cip_pos_cmd_int
,
2824 { "Position Command", "cipm.posicmd",
2825 FT_INT32
, BASE_DEC
, NULL
, 0,
2826 "Cyclic Data Set: Position Command (DINT)", HFILL
}
2829 { "Velocity Command", "cipm.velcmd",
2830 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2831 "Cyclic Data Set: Velocity Command", HFILL
}
2833 { &hf_cip_accel_cmd
,
2834 { "Acceleration Command", "cipm.accelcmd",
2835 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2836 "Cyclic Data Set: Acceleration Command", HFILL
}
2839 { "Torque Command", "cipm.torquecmd",
2840 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2841 "Cyclic Data Set: Torque Command", HFILL
}
2844 { "Position Trim", "cipm.postrim",
2845 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2846 "Cyclic Data Set: Position Trim", HFILL
}
2849 { "Velocity Trim", "cipm.veltrim",
2850 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2851 "Cyclic Data Set: Velocity Trim", HFILL
}
2853 { &hf_cip_accel_trim
,
2854 { "Acceleration Trim", "cipm.acceltrim",
2855 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2856 "Cyclic Data Set: Acceleration Trim", HFILL
}
2859 { "Torque Trim", "cipm.trqtrim",
2860 FT_FLOAT
, BASE_NONE
, NULL
, 0,
2861 "Cyclic Data Set: Torque Trim", HFILL
}
2865 /* Setup protocol subtree array, these will help Wireshark remember
2866 * if the subtree should be expanded as the user moves through packets */
2867 static gint
*cip_subtree
[] = {
2869 &ett_cont_dev_header
,
2873 &ett_inst_data_header
,
2874 &ett_cyclic_data_block
,
2876 &ett_feedback_config
,
2877 &ett_command_data_set
,
2878 &ett_actual_data_set
,
2879 &ett_status_data_set
,
2880 &ett_interp_control
,
2883 &ett_event_check_ctrl
,
2884 &ett_event_check_sts
,
2886 &ett_get_axis_attribute
,
2887 &ett_set_axis_attribute
,
2888 &ett_get_axis_attr_list
,
2889 &ett_set_axis_attr_list
,
2891 &ett_axis_status_set
,
2892 &ett_command_control
2895 /* Create a CIP Motion protocol handle */
2896 proto_cipmotion
= proto_register_protocol(
2897 "Common Industrial Protocol, Motion", /* Full name of protocol */
2898 "CIP Motion", /* Short name of protocol */
2899 "cipm"); /* Abbreviated name of protocol */
2901 /* Register the header fields with the protocol */
2902 proto_register_field_array(proto_cipmotion
, hf
, array_length(hf
));
2904 /* Register the subtrees for the protocol dissection */
2905 proto_register_subtree_array(cip_subtree
, array_length(cip_subtree
));
2907 register_dissector( "cipmotion", dissect_cipmotion
, proto_cipmotion
);
2911 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2916 * indent-tabs-mode: nil
2919 * ex: set shiftwidth=3 tabstop=8 expandtab:
2920 * :indentSize=3:tabSize=8:noTabs=true: