Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-cipmotion.c
Warning:line 1222, column 4
Value stored to 'bytes_used' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-cipmotion.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-10-31-100332-3661-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-cipmotion.c
1/* packet-cipmotion.c
2 * Routines for CIP (Common Industrial Protocol) Motion dissection
3 * CIP Motion Home: www.odva.org
4 *
5 * This dissector includes items from:
6 * CIP Volume 9: CIP Motion, Edition 1.13
7 *
8 * Copyright 2006-2007
9 * Benjamin M. Stocks <bmstocks@ra.rockwell.com>
10 *
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
14 *
15 * SPDX-License-Identifier: GPL-2.0-or-later
16 */
17
18#include "config.h"
19
20#include <epan/packet.h>
21#include <epan/expert.h>
22#include <epan/unit_strings.h>
23
24#include <wsutil/ws_roundup.h>
25
26#include "packet-cipmotion.h"
27
28#include "packet-cip.h"
29#include "packet-enip.h"
30
31void proto_register_cipmotion(void);
32/* The entry point to the actual dissection is: dissect_cipmotion */
33void proto_reg_handoff_cipmotion(void);
34
35/* Protocol handle for CIP Motion */
36static int proto_cipmotion;
37static int proto_cipmotion3;
38
39/* Header field identifiers, these are registered in the
40 * proto_register_cipmotion function along with the bites/bytes
41 * they represent */
42static int hf_cip_format;
43static int hf_cip_revision;
44static int hf_cip_class1_seqnum;
45static int hf_configuration_block_format_rev;
46static int hf_configuration_block_drive_power_struct_id;
47static int hf_cip_updateid;
48static int hf_cip_instance_cnt;
49static int hf_cip_last_update;
50static int hf_cip_node_status;
51static int hf_cip_node_control;
52static int hf_cip_node_control_remote;
53static int hf_cip_node_control_sync;
54static int hf_cip_node_data_valid;
55static int hf_cip_node_fault_reset;
56static int hf_cip_node_device_faulted;
57static int hf_cip_time_data_set;
58static int hf_cip_time_data_stamp;
59static int hf_cip_time_data_offset;
60static int hf_cip_time_data_diag;
61static int hf_cip_time_data_time_diag;
62static int hf_cip_cont_time_stamp;
63static int hf_cip_cont_time_offset;
64static int hf_cip_devc_time_stamp;
65static int hf_cip_devc_time_offset;
66static int hf_cip_lost_update;
67static int hf_cip_late_update;
68static int hf_cip_data_rx_time_stamp;
69static int hf_cip_data_tx_time_stamp;
70static int hf_cip_node_fltalarms;
71static int hf_cip_motor_cntrl;
72static int hf_cip_feedback;
73static int hf_cip_feedback_mode;
74static int hf_cip_feedback_data_type;
75static int hf_cip_controller_update_delay_high_limit;
76static int hf_cip_controller_update_delay_low_limit;
77static int hf_cip_sync_threshold;
78static int hf_cip_step_threshold;
79static int hf_cip_control_method;
80static int hf_cip_feedback_unit_ratio;
81static int hf_cip_velocity_threshold;
82static int hf_cip_velocity_lock_tolerance;
83static int hf_cip_velocity_standstill_window;
84static int hf_cip_proving_configuration;
85static int hf_cip_torque_prove_current;
86static int hf_cip_brake_test_torque;
87static int hf_cip_zero_speed;
88static int hf_cip_zero_speed_time;
89static int hf_cip_dc_bus_voltage;
90static int hf_cip_bus_regulator_action;
91static int hf_cip_inverter_capacity;
92static int hf_cip_converter_thermal_overload_user_limit;
93static int hf_cip_bus_undervoltage_user_limit;
94static int hf_cip_rotary_motor_poles;
95static int hf_cip_rotary_motor_inertia;
96static int hf_cip_rotary_motor_max_speed;
97
98static int hf_connection_configuration_bits;
99static int hf_connection_configuration_bits_power;
100static int hf_connection_configuration_bits_safety_bit_valid;
101static int hf_connection_configuration_bits_allow_network_safety;
102
103static int hf_cip_axis_control;
104static int hf_cip_control_status;
105static int hf_cip_control_status_complete;
106static int hf_cip_control_status_bus_up;
107static int hf_cip_control_status_bus_unload;
108static int hf_cip_control_status_power_loss;
109static int hf_cip_axis_response;
110static int hf_cip_axis_resp_stat;
111static int hf_cip_cmd_data_pos_cmd;
112static int hf_cip_cmd_data_vel_cmd;
113static int hf_cip_cmd_data_acc_cmd;
114static int hf_cip_cmd_data_trq_cmd;
115static int hf_cip_cmd_data_unwind_cycle_count;
116static int hf_cip_cmd_data_pos_displacement;
117static int hf_cip_act_data_pos;
118static int hf_cip_act_data_vel;
119static int hf_cip_act_data_acc;
120static int hf_cip_act_unwind_cycle_count;
121static int hf_cip_act_pos_displacement;
122static int hf_cip_sts_flt;
123static int hf_cip_sts_alrm;
124static int hf_cip_sts_sts;
125static int hf_cip_sts_iosts;
126static int hf_cip_sts_axis_safety;
127static int hf_cip_intrp;
128static int hf_cip_position_data_type;
129static int hf_cip_axis_state;
130static int hf_cip_evnt_ctrl_reg1_pos;
131static int hf_cip_evnt_ctrl_reg1_neg;
132static int hf_cip_evnt_ctrl_reg2_pos;
133static int hf_cip_evnt_ctrl_reg2_neg;
134static int hf_cip_evnt_ctrl_reg1_posrearm;
135static int hf_cip_evnt_ctrl_reg1_negrearm;
136static int hf_cip_evnt_ctrl_reg2_posrearm;
137static int hf_cip_evnt_ctrl_reg2_negrearm;
138static int hf_cip_evnt_ctrl_marker_pos;
139static int hf_cip_evnt_ctrl_marker_neg;
140static int hf_cip_evnt_ctrl_home_pos;
141static int hf_cip_evnt_ctrl_home_neg;
142static int hf_cip_evnt_ctrl_home_pp;
143static int hf_cip_evnt_ctrl_home_pm;
144static int hf_cip_evnt_ctrl_home_mp;
145static int hf_cip_evnt_ctrl_home_mm;
146static int hf_cip_evnt_ctrl_acks;
147static int hf_cip_evnt_extend_format;
148static int hf_cip_evnt_sts_reg1_pos;
149static int hf_cip_evnt_sts_reg1_neg;
150static int hf_cip_evnt_sts_reg2_pos;
151static int hf_cip_evnt_sts_reg2_neg;
152static int hf_cip_evnt_sts_reg1_posrearm;
153static int hf_cip_evnt_sts_reg1_negrearm;
154static int hf_cip_evnt_sts_reg2_posrearm;
155static int hf_cip_evnt_sts_reg2_negrearm;
156static int hf_cip_evnt_sts_marker_pos;
157static int hf_cip_evnt_sts_marker_neg;
158static int hf_cip_evnt_sts_home_pos;
159static int hf_cip_evnt_sts_home_neg;
160static int hf_cip_evnt_sts_home_pp;
161static int hf_cip_evnt_sts_home_pm;
162static int hf_cip_evnt_sts_home_mp;
163static int hf_cip_evnt_sts_home_mm;
164static int hf_cip_evnt_sts_nfs;
165static int hf_cip_evnt_sts_stat;
166static int hf_cip_evnt_type;
167static int hf_cip_svc_code;
168static int hf_cip_svc_sts;
169static int hf_cip_svc_set_axis_attr_sts;
170static int hf_cip_svc_get_axis_attr_sts;
171static int hf_cip_svc_transction;
172static int hf_cip_svc_ext_status;
173static int hf_cip_svc_data;
174static int hf_cip_ptp_grandmaster;
175static int hf_cip_axis_alarm;
176static int hf_cip_axis_fault;
177static int hf_cip_axis_sts_local_ctrl;
178static int hf_cip_axis_sts_alarm;
179static int hf_cip_axis_sts_dc_bus;
180static int hf_cip_axis_sts_pwr_struct;
181static int hf_cip_axis_sts_flux_up;
182static int hf_cip_axis_sts_tracking;
183static int hf_cip_axis_sts_pos_lock;
184static int hf_cip_axis_sts_vel_lock;
185static int hf_cip_axis_sts_vel_standstill;
186static int hf_cip_axis_sts_vel_threshold;
187static int hf_cip_axis_sts_vel_limit;
188static int hf_cip_axis_sts_acc_limit;
189static int hf_cip_axis_sts_dec_limit;
190static int hf_cip_axis_sts_torque_threshold;
191static int hf_cip_axis_sts_torque_limit;
192static int hf_cip_axis_sts_cur_limit;
193static int hf_cip_axis_sts_therm_limit;
194static int hf_cip_axis_sts_feedback_integ;
195static int hf_cip_axis_sts_shutdown;
196static int hf_cip_axis_sts_in_process;
197static int hf_cip_axis_sts_dc_bus_unload;
198static int hf_cip_axis_sts_ac_pwr_loss;
199static int hf_cip_axis_sts_pos_cntrl_mode;
200static int hf_cip_axis_sts_vel_cntrl_mode;
201static int hf_cip_axis_sts_trq_cntrl_mode;
202
203static int hf_cip_axis_status2;
204static int hf_cip_axis_sts2_motor;
205static int hf_cip_axis_sts2_regenerate;
206static int hf_cip_axis_sts2_ride_thru;
207static int hf_cip_axis_sts2_ac_line_sync;
208static int hf_cip_axis_sts2_bus_volt_lock;
209static int hf_cip_axis_sts2_react_pwr_only;
210static int hf_cip_axis_sts2_volt_ctrl_mode;
211static int hf_cip_axis_sts2_pwr_loss;
212static int hf_cip_axis_sts2_ac_volt_sag;
213static int hf_cip_axis_sts2_ac_phase_loss;
214static int hf_cip_axis_sts2_ac_freq_change;
215static int hf_cip_axis_sts2_ac_sync_loss;
216static int hf_cip_axis_sts2_single_phase;
217static int hf_cip_axis_sts2_bus_volt_limit;
218static int hf_cip_axis_sts2_bus_volt_rate_limit;
219static int hf_cip_axis_sts2_active_current_rate_limit;
220static int hf_cip_axis_sts2_reactive_current_rate_limit;
221static int hf_cip_axis_sts2_reactive_pwr_limit;
222static int hf_cip_axis_sts2_reactive_pwr_rate_limit;
223static int hf_cip_axis_sts2_active_current_limit;
224static int hf_cip_axis_sts2_reactive_current_limit;
225static int hf_cip_axis_sts2_motor_pwr_limit;
226static int hf_cip_axis_sts2_regen_pwr_limit;
227static int hf_cip_axis_sts2_convert_therm_limit;
228
229static int hf_cip_cyclic_wrt_data;
230static int hf_cip_cyclic_rd_data;
231static int hf_cip_cyclic_write_blk;
232static int hf_cip_cyclic_read_blk;
233static int hf_cip_cyclic_write_sts;
234static int hf_cip_cyclic_read_sts;
235static int hf_cip_attribute_data;
236static int hf_cip_event_checking;
237static int hf_cip_event_ack;
238static int hf_cip_event_status;
239static int hf_cip_event_id;
240static int hf_cip_event_pos;
241static int hf_cip_event_ts;
242static int hf_cip_pos_cmd;
243static int hf_cip_pos_cmd_int;
244static int hf_cip_vel_cmd;
245static int hf_cip_accel_cmd;
246static int hf_cip_trq_cmd;
247static int hf_cip_pos_trim;
248static int hf_cip_vel_trim;
249static int hf_cip_accel_trim;
250static int hf_cip_trq_trim;
251static int hf_cip_act_pos;
252static int hf_cip_act_pos_64;
253static int hf_cip_act_vel;
254static int hf_cip_act_accel;
255static int hf_cip_fault_type;
256static int hf_cip_fault_sub_code;
257static int hf_cip_fault_action;
258static int hf_cip_fault_time_stamp;
259static int hf_cip_alarm_type;
260static int hf_cip_alarm_sub_code;
261static int hf_cip_alarm_state;
262static int hf_cip_alarm_time_stamp;
263static int hf_cip_axis_status;
264static int hf_cip_axis_status_mfg;
265static int hf_cip_axis_io_status;
266static int hf_cip_axis_io_status_mfg;
267static int hf_cip_axis_safety_status;
268static int hf_cip_axis_safety_status_mfg;
269static int hf_cip_axis_safety_state;
270static int hf_cip_cmd_data_set;
271static int hf_cip_act_data_set;
272static int hf_cip_sts_data_set;
273static int hf_cip_group_sync;
274static int hf_cip_command_control;
275
276static int hf_get_axis_attr_list_attribute_cnt;
277static int hf_get_axis_attr_list_attribute_id;
278static int hf_get_axis_attr_list_dimension;
279static int hf_get_axis_attr_list_element_size;
280static int hf_get_axis_attr_list_start_index;
281static int hf_get_axis_attr_list_data_elements;
282static int hf_set_axis_attr_list_attribute_cnt;
283static int hf_set_axis_attr_list_attribute_id;
284static int hf_set_axis_attr_list_dimension;
285static int hf_set_axis_attr_list_element_size;
286static int hf_set_axis_attr_list_start_index;
287static int hf_set_axis_attr_list_data_elements;
288static int hf_set_cyclic_list_attribute_cnt;
289static int hf_set_cyclic_list_attribute_id;
290static int hf_set_cyclic_list_read_block_id;
291static int hf_set_cyclic_list_attr_sts;
292static int hf_var_devce_instance;
293static int hf_var_devce_instance_block_size;
294static int hf_var_devce_cyclic_block_size;
295static int hf_var_devce_cyclic_data_block_size;
296static int hf_var_devce_cyclic_rw_block_size;
297static int hf_var_devce_event_block_size;
298static int hf_var_devce_service_block_size;
299static int hf_cip_data;
300
301/* Subtree pointers for the dissection */
302static int ett_cipmotion;
303static int ett_cont_dev_header;
304static int ett_control_status;
305static int ett_node_control;
306static int ett_node_status;
307static int ett_time_data_set;
308static int ett_inst_data_header;
309static int ett_cyclic_data_block;
310static int ett_cyclic_command_data;
311static int ett_feedback_mode;
312static int ett_connection_configuration_bits;
313static int ett_control_mode;
314static int ett_feedback_config;
315static int ett_command_data_set;
316static int ett_actual_data_set;
317static int ett_status_data_set;
318static int ett_interp_control;
319static int ett_cyclic_rd_wt;
320static int ett_event;
321static int ett_event_check_ctrl;
322static int ett_event_check_sts;
323static int ett_service;
324static int ett_get_axis_attribute;
325static int ett_set_axis_attribute;
326static int ett_get_axis_attr_list;
327static int ett_set_axis_attr_list;
328static int ett_set_cyclic_list;
329static int ett_group_sync;
330static int ett_axis_status_set;
331static int ett_command_control;
332static int ett_configuration_block;
333
334static expert_field ei_format_rev_conn_pt;
335
336static dissector_handle_t cipmotion_handle;
337static dissector_handle_t cipmotion3_handle;
338
339static bool_Bool display_full_attribute_data;
340
341/* These are the BITMASKS for the Time Data Set header field */
342#define TIME_DATA_SET_TIME_STAMP0x1 0x1
343#define TIME_DATA_SET_TIME_OFFSET0x2 0x2
344#define TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4 0x4
345#define TIME_DATA_SET_TIME_DIAGNOSTICS0x8 0x8
346
347/* These are the BITMASKS for the Command Data Set cyclic field */
348#define COMMAND_DATA_SET_POSITION0x01 0x01
349#define COMMAND_DATA_SET_VELOCITY0x02 0x02
350#define COMMAND_DATA_SET_ACCELERATION0x04 0x04
351#define COMMAND_DATA_SET_TORQUE0x08 0x08
352#define COMMAND_DATA_SET_UNWIND_CYCLE_COUNT0x40 0x40
353#define COMMAND_DATA_SET_POSITION_DISPLACE0x80 0x80
354
355/* These are the BITMASKS for the Actual Data Set cyclic field */
356#define ACTUAL_DATA_SET_POSITION0x01 0x01
357#define ACTUAL_DATA_SET_VELOCITY0x02 0x02
358#define ACTUAL_DATA_SET_ACCELERATION0x04 0x04
359#define ACTUAL_DATA_SET_UNWIND_CYCLE_COUNT0x40 0x40
360#define ACTUAL_DATA_SET_POSITION_DISPLACE0x80 0x80
361
362/* These are the BITMASKS for the Status Data Set cyclic field */
363#define STATUS_DATA_SET_AXIS_FAULT0x01 0x01
364#define STATUS_DATA_SET_AXIS_ALARM0x02 0x02
365#define STATUS_DATA_SET_AXIS_STATUS0x04 0x04
366#define STATUS_DATA_SET_AXIS_IO_STATUS0x08 0x08
367#define STATUS_DATA_SET_AXIS_SAFETY0x10 0x10
368
369/* These are the BITMASKS for the Command Control cyclic field */
370#define COMMAND_CONTROL_TARGET_UPDATE0x03 0x03
371#define COMMAND_CONTROL_POSITION_DATA_TYPE0x0C 0x0C
372
373/* These are the VALUES of the connection format header field of the
374 * CIP Motion protocol */
375#define FORMAT_FIXED_CONTROL_TO_DEVICE2 2
376#define FORMAT_FIXED_DEVICE_TO_CONTROL3 3
377#define FORMAT_VAR_CONTROL_TO_DEVICE6 6
378#define FORMAT_VAR_DEVICE_TO_CONTROL7 7
379
380#define FEEDBACK_MODE_BITS0x0F 0x0F
381#define FEEDBACK_DATA_TYPE_BITS0x30 0x30
382
383/* Translate function to string - connection format values */
384static const value_string cip_con_format_vals[] = {
385 { FORMAT_FIXED_CONTROL_TO_DEVICE2, "Fixed Controller-to-Device" },
386 { FORMAT_FIXED_DEVICE_TO_CONTROL3, "Fixed Device-to-Controller" },
387 { FORMAT_VAR_CONTROL_TO_DEVICE6, "Variable Controller-to-Device" },
388 { FORMAT_VAR_DEVICE_TO_CONTROL7, "Variable Device-to-Controller" },
389 { 0, NULL((void*)0) }
390};
391
392/* Translate function to string - motor control mode values */
393static const value_string cip_motor_control_vals[] = {
394 { 0, "No Control" },
395 { 1, "Position Control" },
396 { 2, "Velocity Control" },
397 { 3, "Acceleration Control" },
398 { 4, "Torque Control" },
399 { 0, NULL((void*)0) }
400};
401
402/* Translate function to string - feedback mode values */
403static const value_string cip_feedback_mode_vals[] = {
404 { 0, "No Feedback" },
405 { 1, "Master Feedback" },
406 { 2, "Motor Feedback" },
407 { 3, "Load Feedback" },
408 { 4, "Dual Feedback" },
409 { 0, NULL((void*)0) }
410};
411
412static const value_string cip_feedback_type_vals[] = {
413 { 0, "DINT" },
414 { 1, "LINT" },
415 { 0, NULL((void*)0) }
416};
417
418/* Translate function to string - axis control values */
419static const value_string cip_axis_control_vals[] =
420{
421 { 0, "No Request" },
422 { 1, "Enable Request" },
423 { 2, "Disable Request" },
424 { 3, "Shutdown Request" },
425 { 4, "Shutdown Reset Request" },
426 { 5, "Abort Request" },
427 { 6, "Fault Reset Request" },
428 { 7, "Stop Process" },
429 { 8, "Change Actual Pos" },
430 { 9, "Change Command Pos Ref" },
431 { 127, "Cancel Request" },
432 { 0, NULL((void*)0) }
433};
434
435/* Translate function to string - group sync Status */
436static const value_string cip_sync_status_vals[] =
437{
438 { 0, "Synchronized" },
439 { 1, "Not Synchronized" },
440 { 2, "Wrong Grandmaster" },
441 { 3, "Clock Skew Detected" },
442 { 0, NULL((void*)0) }
443};
444
445/* Translate function to string - command target update */
446static const value_string cip_interpolation_vals[] = {
447 { 0, "Immediate" },
448 { 1, "Extrapolate (+1)" },
449 { 2, "Interpolate (+2)" },
450 { 0, NULL((void*)0) }
451};
452
453/* These are the VALUES for the Command Position Data Type */
454#define POSITION_DATA_LREAL0x00 0x00
455#define POSITION_DATA_DINT0x01 0x01
456
457/* Translate function to string - position data type */
458static const value_string cip_pos_data_type_vals[] = {
459 { POSITION_DATA_LREAL0x00, "LREAL (64-bit Float)" },
460 { POSITION_DATA_DINT0x01, "DINT (32-bit Integer)" },
461 { 0, NULL((void*)0) }
462};
463
464/* Translate function to string - axis response values */
465static const value_string cip_axis_response_vals[] = {
466 { 0, "No Acknowledge" },
467 { 1, "Enable Acknowledge" },
468 { 2, "Disable Acknowledge" },
469 { 3, "Shutdown Acknowledge" },
470 { 4, "Shutdown Reset Acknowledge" },
471 { 5, "Abort Acknowledge" },
472 { 6, "Fault Reset Acknowledge" },
473 { 7, "Stop Process Acknowledge" },
474 { 8, "Change Actual Position Reference Acknowledge" },
475 { 9, "Change Command Position Reference Acknowledge" },
476 { 127, "Cancel Acknowledge" },
477 { 0, NULL((void*)0) }
478};
479
480/* Translate function to string - axis state values */
481static const value_string cip_axis_state_vals[] = {
482 { 0, "Initializing" },
483 { 1, "Pre-Charge" },
484 { 2, "Stopped" },
485 { 3, "Starting" },
486 { 4, "Running" },
487 { 5, "Testing" },
488 { 6, "Stopping" },
489 { 7, "Aborting" },
490 { 8, "Major Faulted" },
491 { 9, "Start Inhibited" },
492 { 10, "Shutdown" },
493 { 0, NULL((void*)0) }
494};
495
496/* Translate function to string - event type values */
497static const value_string cip_event_type_vals[] = {
498 { 0, "Registration 1 Positive Edge" },
499 { 1, "Registration 1 Negative Edge" },
500 { 2, "Registration 2 Positive Edge" },
501 { 3, "Registration 2 Negative Edge" },
502 { 4, "Marker Positive Edge" },
503 { 5, "Marker Negative Edge" },
504 { 6, "Home Switch Positive Edge" },
505 { 7, "Home Switch Negative Edge" },
506 { 8, "Home Switch Marker ++" },
507 { 9, "Home Switch Marker +-" },
508 { 10, "Home Switch Marker -+" },
509 { 11, "Home Switch Marker --" },
510 { 0, NULL((void*)0) }
511};
512
513#define SC_GET_AXIS_ATTRIBUTE_LIST0x4B 0x4B
514#define SC_SET_AXIS_ATTRIBUTE_LIST0x4C 0x4C
515#define SC_SET_CYCLIC_WRITE_LIST0x4D 0x4D
516#define SC_SET_CYCLIC_READ_LIST0x4E 0x4E
517#define SC_RUN_MOTOR_TEST0x4F 0x4F
518#define SC_GET_MOTOR_TEST_DATA0x50 0x50
519#define SC_RUN_INERTIA_TEST0x51 0x51
520#define SC_GET_INERTIA_TEST_DATA0x52 0x52
521#define SC_RUN_HOOKUP_TEST0x53 0x53
522#define SC_GET_HOOKUP_TEST_DATA0x54 0x54
523
524/* Translate function to string - CIP Service codes */
525static const value_string cip_sc_vals[] = {
526 GENERIC_SC_LIST{ 0x01, "Get Attributes All" }, { 0x02, "Set Attributes All" }
, { 0x03, "Get Attribute List" }, { 0x04, "Set Attribute List"
}, { 0x05, "Reset" }, { 0x06, "Start" }, { 0x07, "Stop" }, {
0x08, "Create" }, { 0x09, "Delete" }, { 0x0A, "Multiple Service Packet"
}, { 0x0D, "Apply Attributes" }, { 0x0E, "Get Attribute Single"
}, { 0x10, "Set Attribute Single" }, { 0x11, "Find Next Object Instance"
}, { 0x15, "Restore" }, { 0x16, "Save" }, { 0x17, "Nop" }, {
0x18, "Get Member" }, { 0x19, "Set Member" }, { 0x1A, "Insert Member"
}, { 0x1B, "Remove Member" }, { 0x1C, "Group Sync" },
527 { SC_GET_AXIS_ATTRIBUTE_LIST0x4B, "Get Axis Attribute List" },
528 { SC_SET_AXIS_ATTRIBUTE_LIST0x4C, "Set Axis Attribute List" },
529 { SC_SET_CYCLIC_WRITE_LIST0x4D, "Set Cyclic Write List" },
530 { SC_SET_CYCLIC_READ_LIST0x4E, "Set Cyclic Read List" },
531 { SC_RUN_MOTOR_TEST0x4F, "Run Motor Test" },
532 { SC_GET_MOTOR_TEST_DATA0x50, "Get Motor Test Data" },
533 { SC_RUN_INERTIA_TEST0x51, "Run Inertia Test" },
534 { SC_GET_INERTIA_TEST_DATA0x52, "Get Inertia Test Data" },
535 { SC_RUN_HOOKUP_TEST0x53, "Run Hookup Test" },
536 { SC_GET_HOOKUP_TEST_DATA0x54, "Get Hookup Test Data" },
537 { 0, NULL((void*)0) }
538};
539
540static int dissect_axis_status(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
541 int offset, int total_len _U___attribute__((unused)))
542{
543 static int* const bits[] = {
544 &hf_cip_axis_sts_local_ctrl,
545 &hf_cip_axis_sts_alarm,
546 &hf_cip_axis_sts_dc_bus,
547 &hf_cip_axis_sts_pwr_struct,
548 &hf_cip_axis_sts_flux_up,
549 &hf_cip_axis_sts_tracking,
550 &hf_cip_axis_sts_pos_lock,
551 &hf_cip_axis_sts_vel_lock,
552 &hf_cip_axis_sts_vel_standstill,
553 &hf_cip_axis_sts_vel_threshold,
554 &hf_cip_axis_sts_vel_limit,
555 &hf_cip_axis_sts_acc_limit,
556 &hf_cip_axis_sts_dec_limit,
557 &hf_cip_axis_sts_torque_threshold,
558 &hf_cip_axis_sts_torque_limit,
559 &hf_cip_axis_sts_cur_limit,
560 &hf_cip_axis_sts_therm_limit,
561 &hf_cip_axis_sts_feedback_integ,
562 &hf_cip_axis_sts_shutdown,
563 &hf_cip_axis_sts_in_process,
564 &hf_cip_axis_sts_dc_bus_unload,
565 &hf_cip_axis_sts_ac_pwr_loss,
566 &hf_cip_axis_sts_pos_cntrl_mode,
567 &hf_cip_axis_sts_vel_cntrl_mode,
568 &hf_cip_axis_sts_trq_cntrl_mode,
569 NULL((void*)0)
570 };
571
572 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_axis_status, ett_axis_status_set, bits, ENC_LITTLE_ENDIAN0x80000000);
573
574 return 4;
575}
576
577static int dissect_axis_status2(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
578 int offset, int total_len _U___attribute__((unused)))
579{
580 static int* const bits[] = {
581 &hf_cip_axis_sts2_motor,
582 &hf_cip_axis_sts2_regenerate,
583 &hf_cip_axis_sts2_ride_thru,
584 &hf_cip_axis_sts2_ac_line_sync,
585 &hf_cip_axis_sts2_bus_volt_lock,
586 &hf_cip_axis_sts2_react_pwr_only,
587 &hf_cip_axis_sts2_volt_ctrl_mode,
588 &hf_cip_axis_sts2_pwr_loss,
589 &hf_cip_axis_sts2_ac_volt_sag,
590 &hf_cip_axis_sts2_ac_phase_loss,
591 &hf_cip_axis_sts2_ac_freq_change,
592 &hf_cip_axis_sts2_ac_sync_loss,
593 &hf_cip_axis_sts2_single_phase,
594 &hf_cip_axis_sts2_bus_volt_limit,
595 &hf_cip_axis_sts2_bus_volt_rate_limit,
596 &hf_cip_axis_sts2_active_current_rate_limit,
597 &hf_cip_axis_sts2_reactive_current_rate_limit,
598 &hf_cip_axis_sts2_reactive_pwr_limit,
599 &hf_cip_axis_sts2_reactive_pwr_rate_limit,
600 &hf_cip_axis_sts2_active_current_limit,
601 &hf_cip_axis_sts2_reactive_current_limit,
602 &hf_cip_axis_sts2_motor_pwr_limit,
603 &hf_cip_axis_sts2_regen_pwr_limit,
604 &hf_cip_axis_sts2_convert_therm_limit,
605 NULL((void*)0)
606 };
607
608 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_axis_status2, ett_axis_status_set, bits, ENC_LITTLE_ENDIAN0x80000000);
609
610 return 4;
611}
612
613static int dissect_event_checking_control(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
614 int offset, int total_len _U___attribute__((unused)))
615{
616 static int* const bits[] = {
617 &hf_cip_evnt_ctrl_reg1_pos,
618 &hf_cip_evnt_ctrl_reg1_neg,
619 &hf_cip_evnt_ctrl_reg2_pos,
620 &hf_cip_evnt_ctrl_reg2_neg,
621 &hf_cip_evnt_ctrl_reg1_posrearm,
622 &hf_cip_evnt_ctrl_reg1_negrearm,
623 &hf_cip_evnt_ctrl_reg2_posrearm,
624 &hf_cip_evnt_ctrl_reg2_negrearm,
625 &hf_cip_evnt_ctrl_marker_pos,
626 &hf_cip_evnt_ctrl_marker_neg,
627 &hf_cip_evnt_ctrl_home_pos,
628 &hf_cip_evnt_ctrl_home_neg,
629 &hf_cip_evnt_ctrl_home_pp,
630 &hf_cip_evnt_ctrl_home_pm,
631 &hf_cip_evnt_ctrl_home_mp,
632 &hf_cip_evnt_ctrl_home_mm,
633 &hf_cip_evnt_ctrl_acks,
634 // The dissector will indicate if the protocol is requesting an extended event format but will not dissect it.
635 &hf_cip_evnt_extend_format,
636 NULL((void*)0)
637 };
638
639 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_event_checking, ett_event_check_ctrl, bits, ENC_LITTLE_ENDIAN0x80000000);
640
641 return 4;
642}
643
644static int dissect_event_checking_status(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
645 int offset, int total_len _U___attribute__((unused)))
646{
647 static int* const bits[] = {
648 &hf_cip_evnt_sts_reg1_pos,
649 &hf_cip_evnt_sts_reg1_neg,
650 &hf_cip_evnt_sts_reg2_pos,
651 &hf_cip_evnt_sts_reg2_neg,
652 &hf_cip_evnt_sts_reg1_posrearm,
653 &hf_cip_evnt_sts_reg1_negrearm,
654 &hf_cip_evnt_sts_reg2_posrearm,
655 &hf_cip_evnt_sts_reg2_negrearm,
656 &hf_cip_evnt_sts_marker_pos,
657 &hf_cip_evnt_sts_marker_neg,
658 &hf_cip_evnt_sts_home_pos,
659 &hf_cip_evnt_sts_home_neg,
660 &hf_cip_evnt_sts_home_pp,
661 &hf_cip_evnt_sts_home_pm,
662 &hf_cip_evnt_sts_home_mp,
663 &hf_cip_evnt_sts_home_mm,
664 &hf_cip_evnt_sts_nfs,
665 // The dissector will indicate if the protocol is requesting an extended event format but will not dissect it.
666 &hf_cip_evnt_extend_format,
667 NULL((void*)0)
668 };
669
670 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_event_status, ett_event_check_sts, bits, ENC_LITTLE_ENDIAN0x80000000);
671
672 return 4;
673}
674
675static int dissect_actual_data_set_bits(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
676 int offset, int total_len _U___attribute__((unused)))
677{
678 static int* const bits[] = {
679 &hf_cip_act_data_pos,
680 &hf_cip_act_data_vel,
681 &hf_cip_act_data_acc,
682 &hf_cip_act_unwind_cycle_count,
683 &hf_cip_act_pos_displacement,
684 NULL((void*)0)
685 };
686
687 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_act_data_set, ett_actual_data_set, bits, ENC_LITTLE_ENDIAN0x80000000);
688
689 return 1;
690}
691
692static int dissect_command_data_set_bits(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
693 int offset, int total_len _U___attribute__((unused)))
694{
695 static int* const bits[] = {
696 &hf_cip_cmd_data_pos_cmd,
697 &hf_cip_cmd_data_vel_cmd,
698 &hf_cip_cmd_data_acc_cmd,
699 &hf_cip_cmd_data_trq_cmd,
700 &hf_cip_cmd_data_unwind_cycle_count,
701 &hf_cip_cmd_data_pos_displacement,
702 NULL((void*)0)
703 };
704
705 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_cmd_data_set, ett_command_data_set, bits, ENC_LITTLE_ENDIAN0x80000000);
706
707 return 1;
708}
709
710static int dissect_command_control(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
711 int offset, int total_len _U___attribute__((unused)))
712{
713 static int* const bits[] = {
714 &hf_cip_intrp,
715 &hf_cip_position_data_type,
716 NULL((void*)0)
717 };
718
719 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_command_control, ett_command_control, bits, ENC_LITTLE_ENDIAN0x80000000);
720
721 return 1;
722}
723
724static int dissect_status_data_set_bits(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
725 int offset, int total_len _U___attribute__((unused)))
726{
727 static int* const bits[] = {
728 &hf_cip_sts_flt,
729 &hf_cip_sts_alrm,
730 &hf_cip_sts_sts,
731 &hf_cip_sts_iosts,
732 &hf_cip_sts_axis_safety,
733 NULL((void*)0)
734 };
735
736 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_sts_data_set, ett_status_data_set, bits, ENC_LITTLE_ENDIAN0x80000000);
737
738 return 1;
739}
740
741static int dissect_node_control(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
742 int offset, int total_len _U___attribute__((unused)))
743{
744 static int* const bits[] = {
745 &hf_cip_node_control_remote,
746 &hf_cip_node_control_sync,
747 &hf_cip_node_data_valid,
748 &hf_cip_node_fault_reset,
749 NULL((void*)0)
750 };
751
752 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_node_control, ett_node_control, bits, ENC_LITTLE_ENDIAN0x80000000);
753
754 return 1;
755}
756
757static int dissect_node_status(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
758 int offset, int total_len _U___attribute__((unused)))
759{
760 static int* const bits[] = {
761 &hf_cip_node_control_remote,
762 &hf_cip_node_control_sync,
763 &hf_cip_node_data_valid,
764 &hf_cip_node_device_faulted,
765 NULL((void*)0)
766 };
767
768 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_node_status, ett_node_status, bits, ENC_LITTLE_ENDIAN0x80000000);
769
770 return 1;
771}
772
773static int dissect_time_data_set(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
774 int offset, int total_len _U___attribute__((unused)))
775{
776 static int* const bits[] = {
777 &hf_cip_time_data_stamp,
778 &hf_cip_time_data_offset,
779 &hf_cip_time_data_diag,
780 &hf_cip_time_data_time_diag,
781 NULL((void*)0)
782 };
783
784 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_time_data_set, ett_time_data_set, bits, ENC_LITTLE_ENDIAN0x80000000);
785
786 return 1;
787}
788
789static int dissect_control_status(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
790 int offset, int total_len _U___attribute__((unused)))
791{
792 static int* const bits[] = {
793 &hf_cip_control_status_complete,
794 &hf_cip_control_status_bus_up,
795 &hf_cip_control_status_bus_unload,
796 &hf_cip_control_status_power_loss,
797 NULL((void*)0)
798 };
799
800 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_control_status, ett_control_status, bits, ENC_LITTLE_ENDIAN0x80000000);
801
802 return 1;
803}
804
805static int dissect_feedback_mode(packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, proto_item *item _U___attribute__((unused)), tvbuff_t *tvb,
806 int offset, int total_len _U___attribute__((unused)))
807{
808 static int* const bits[] = {
809 &hf_cip_feedback_mode,
810 &hf_cip_feedback_data_type,
811 NULL((void*)0)
812 };
813
814 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_feedback, ett_feedback_mode, bits, ENC_LITTLE_ENDIAN0x80000000);
815
816 return 1;
817}
818
819static int dissect_connection_configuration_bits(packet_info* pinfo _U___attribute__((unused)), proto_tree* tree, proto_item* item _U___attribute__((unused)), tvbuff_t* tvb,
820 int offset, int total_len _U___attribute__((unused)))
821{
822 static int* const bits[] = {
823 &hf_connection_configuration_bits_power,
824 &hf_connection_configuration_bits_safety_bit_valid,
825 &hf_connection_configuration_bits_allow_network_safety,
826 NULL((void*)0)
827 };
828
829 proto_tree_add_bitmask(tree, tvb, offset, hf_connection_configuration_bits, ett_connection_configuration_bits, bits, ENC_LITTLE_ENDIAN0x80000000);
830
831 return 1;
832}
833
834const attribute_info_t cip_motion_attribute_vals[] = {
835 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 14, -1, "Node Control", cip_dissector_func, NULL((void*)0), dissect_node_control },
836 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 15, -1, "Node Status", cip_dissector_func, NULL((void*)0), dissect_node_status },
837 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 21, -1, "Controller Update Delay High Limit", cip_usint, &hf_cip_controller_update_delay_high_limit, NULL((void*)0) },
838 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 22, -1, "Controller Update Delay Low Limit", cip_usint, &hf_cip_controller_update_delay_low_limit, NULL((void*)0) },
839 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 29, -1, "Sync Threshold", cip_udint, &hf_cip_sync_threshold, NULL((void*)0) },
840 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 31, -1, "Time Data Set", cip_dissector_func, NULL((void*)0), dissect_time_data_set },
841 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 34, -1, "Drive Power Structure Class ID", cip_udint, &hf_configuration_block_drive_power_struct_id, NULL((void*)0) },
842 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 35, -1, "Step Threshold", cip_udint, &hf_cip_step_threshold, NULL((void*)0) },
843 { CI_CLS_MOTION0x42, CIP_ATTR_CLASS(1), 36, -1, "Connection Configuration Bits", cip_dissector_func, NULL((void*)0), dissect_connection_configuration_bits },
844 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 40, -1, "Control Mode", cip_usint, &hf_cip_motor_cntrl, NULL((void*)0) },
845 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 41, -1, "Control Method", cip_usint, &hf_cip_control_method, NULL((void*)0) },
846 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 42, -1, "Feedback Mode", cip_dissector_func, NULL((void*)0), dissect_feedback_mode },
847 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 44, -1, "Feedback Unit Ratio", cip_real, &hf_cip_feedback_unit_ratio, NULL((void*)0) },
848 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 60, -1, "Event Checking Control", cip_dissector_func, NULL((void*)0), dissect_event_checking_control },
849 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 61, -1, "Event Checking Status", cip_dissector_func, NULL((void*)0), dissect_event_checking_status },
850 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 89, -1, "Control Status", cip_dissector_func, NULL((void*)0), dissect_control_status },
851 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 90, -1, "Actual Data Set", cip_dissector_func, NULL((void*)0), dissect_actual_data_set_bits },
852 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 91, -1, "Command Data Set", cip_dissector_func, NULL((void*)0), dissect_command_data_set_bits },
853 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 92, -1, "Command Control", cip_dissector_func, NULL((void*)0), dissect_command_control },
854 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 94, -1, "Status Data Set", cip_dissector_func, NULL((void*)0), dissect_status_data_set_bits },
855 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 431, -1, "Position Trim", cip_dint, &hf_cip_pos_trim, NULL((void*)0) },
856 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 451, -1, "Velocity Trim", cip_real, &hf_cip_vel_trim, NULL((void*)0) },
857 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 470, -1, "Velocity Threshold", cip_real, &hf_cip_velocity_threshold, NULL((void*)0) },
858 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 471, -1, "Velocity Lock Tolerance", cip_real, &hf_cip_velocity_lock_tolerance, NULL((void*)0) },
859 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 472, -1, "Velocity Standstill Window", cip_real, &hf_cip_velocity_standstill_window, NULL((void*)0) },
860 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 481, -1, "Acceleration Trim", cip_real, &hf_cip_accel_trim, NULL((void*)0) },
861 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 491, -1, "Torque Trim", cip_real, &hf_cip_trq_trim, NULL((void*)0) },
862 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 590, -1, "Proving Configuration", cip_usint, &hf_cip_proving_configuration, NULL((void*)0) },
863 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 591, -1, "Torque Prove Current", cip_real, &hf_cip_torque_prove_current, NULL((void*)0) },
864 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 592, -1, "Brake Test Torque", cip_real, &hf_cip_brake_test_torque, NULL((void*)0) },
865 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 608, -1, "Zero Speed", cip_real, &hf_cip_zero_speed, NULL((void*)0) },
866 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 609, -1, "Zero Speed Time", cip_real, &hf_cip_zero_speed_time, NULL((void*)0) },
867 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 620, -1, "DC Bus Voltage", cip_real, &hf_cip_dc_bus_voltage, NULL((void*)0) },
868 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 624, -1, "Bus Regulator Action", cip_usint, &hf_cip_bus_regulator_action, NULL((void*)0) },
869 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 636, -1, "Inverter Capacity", cip_real, &hf_cip_inverter_capacity, NULL((void*)0) },
870 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 651, -1, "Axis Status", cip_dissector_func, NULL((void*)0), dissect_axis_status },
871 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 701, -1, "Converter Thermal Overload User Limit", cip_real, &hf_cip_converter_thermal_overload_user_limit, NULL((void*)0) },
872 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 705, -1, "Bus Undervoltage User Limit", cip_real, &hf_cip_bus_undervoltage_user_limit, NULL((void*)0) },
873 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 740, -1, "Axis Status 2", cip_dissector_func, NULL((void*)0), dissect_axis_status2 },
874 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 1329, -1, "Rotary Motor Poles", cip_uint, &hf_cip_rotary_motor_poles, NULL((void*)0) },
875 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 1330, -1, "Rotary Motor Inertia", cip_real, &hf_cip_rotary_motor_inertia, NULL((void*)0) },
876 { CI_CLS_MOTION0x42, CIP_ATTR_INSTANCE(0), 1332, -1, "Rotary Motor Max Speed", cip_real, &hf_cip_rotary_motor_max_speed, NULL((void*)0) },
877};
878
879/*
880 * Function name: dissect_cmd_data_set
881 *
882 * Purpose: Dissect the "Cyclic Command Data" of a Controller-to-Device format message
883 *
884 * Based on the Command Data Set bits of the Cyclic Command Data Block header, display
885 * any of those command values.
886 *
887 * Returns: The number of bytes in the cyclic data used
888 */
889static uint32_t
890dissect_cmd_data_set(uint32_t cmd_data_set, proto_tree* parent_tree, tvbuff_t* tvb, uint32_t offset, bool_Bool lreal_pos, uint32_t avail)
891{
892 // If no Command Data Set bits are set, then we don't need to display any additional data.
893 // avail is the bytes left in the cyclic block. The bits and the block
894 // size are independent; reading past the block steals the next one.
895 if (cmd_data_set == 0 || avail == 0)
896 {
897 return 0;
898 }
899
900 uint32_t bytes_used = 0;
901
902 proto_item* item;
903 proto_tree* tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0, ett_cyclic_command_data, &item, "Cyclic Command Data");
904
905 /* The order of these if statements is VERY important, this is the order the values will
906 * appear in the cyclic data */
907 if ( (cmd_data_set & COMMAND_DATA_SET_POSITION0x01) == COMMAND_DATA_SET_POSITION0x01 )
908 {
909 uint32_t flen = lreal_pos ? 8 : 4;
910
911 /* Based on the Command Position Data Type value embedded in the Command Control
912 * header field the position is either 64-bit floating or 32-bit integer */
913 if (bytes_used + flen > avail) {
914 proto_item_set_len(item, bytes_used);
915 return bytes_used;
916 }
917 if (lreal_pos)
918 {
919 /* Display the command data set position command value */
920 proto_tree_add_item(tree, hf_cip_pos_cmd, tvb, offset + bytes_used, 8, ENC_LITTLE_ENDIAN0x80000000 );
921 }
922 else
923 {
924 /* Display the command data set position command value */
925 proto_tree_add_item(tree, hf_cip_pos_cmd_int, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
926 }
927 bytes_used += flen;
928 }
929
930 if ( (cmd_data_set & COMMAND_DATA_SET_VELOCITY0x02) == COMMAND_DATA_SET_VELOCITY0x02 )
931 {
932 if (bytes_used + 4 > avail) {
933 proto_item_set_len(item, bytes_used);
934 return bytes_used;
935 }
936 /* Display the command data set velocity command value */
937 proto_tree_add_item(tree, hf_cip_vel_cmd, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
938 bytes_used += 4;
939 }
940
941 if ( (cmd_data_set & COMMAND_DATA_SET_ACCELERATION0x04) == COMMAND_DATA_SET_ACCELERATION0x04 )
942 {
943 if (bytes_used + 4 > avail) {
944 proto_item_set_len(item, bytes_used);
945 return bytes_used;
946 }
947 /* Display the command data set acceleration command value */
948 proto_tree_add_item(tree, hf_cip_accel_cmd, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
949 bytes_used += 4;
950 }
951
952 if ( (cmd_data_set & COMMAND_DATA_SET_TORQUE0x08) == COMMAND_DATA_SET_TORQUE0x08 )
953 {
954 if (bytes_used + 4 > avail) {
955 proto_item_set_len(item, bytes_used);
956 return bytes_used;
957 }
958 /* Display the command data set torque command value */
959 proto_tree_add_item(tree, hf_cip_trq_cmd, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
960 bytes_used += 4;
961 }
962
963 proto_item_set_len(item, bytes_used);
964
965 return bytes_used;
966}
967
968
969/*
970 * Function name: dissect_act_data_set
971 *
972 * Purpose: Dissect the "Cyclic Actual Data" of a Device-to-Controller format message
973 *
974 * Based on the Actual Data Set bits of the "Cyclic Actual Data Block" header, display
975 * any of those feedback values.
976 *
977 * Returns: The number of bytes in the cyclic data used
978 */
979static uint32_t
980dissect_act_data_set(uint32_t act_data_set, proto_tree* parent_tree, tvbuff_t* tvb, uint32_t offset, uint8_t feedback_mode, uint32_t avail, bool_Bool *stopped)
981{
982 // If no Actual Data Set bits are set, then we don't need to display any additional data.
983 if (stopped != NULL((void*)0)) {
984 *stopped = false0;
985 }
986 if (act_data_set == 0)
987 {
988 return 0;
989 }
990 if (avail == 0)
991 {
992 if (stopped != NULL((void*)0)) {
993 *stopped = true1;
994 }
995 return 0;
996 }
997
998 uint32_t bytes_used = 0;
999
1000 proto_item* item;
1001 proto_tree* tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0, ett_cyclic_command_data, &item, "Cyclic Actual Data");
1002
1003 /* The order of these if statements is VERY important, this is the order the values will
1004 * appear in the cyclic data */
1005 if ( (act_data_set & ACTUAL_DATA_SET_POSITION0x01) == ACTUAL_DATA_SET_POSITION0x01 )
1006 {
1007 /* Display the actual data set position feedback value in either 32 or 64 bit */
1008 bool_Bool is_64_bit_position = (feedback_mode & FEEDBACK_DATA_TYPE_BITS0x30) == 0x10;
1009 uint32_t flen = is_64_bit_position ? 8 : 4;
1010
1011 if (bytes_used + flen > avail) {
1012 if (stopped != NULL((void*)0)) {
1013 *stopped = true1;
1014 }
1015 proto_item_set_len(item, bytes_used);
1016 return bytes_used;
1017 }
1018 if (is_64_bit_position)
1019 {
1020 proto_tree_add_item(tree, hf_cip_act_pos_64, tvb, offset + bytes_used, 8, ENC_LITTLE_ENDIAN0x80000000);
1021 }
1022 else
1023 {
1024 proto_tree_add_item(tree, hf_cip_act_pos, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1025 }
1026 bytes_used += flen;
1027 }
1028
1029 if ( (act_data_set & ACTUAL_DATA_SET_VELOCITY0x02) == ACTUAL_DATA_SET_VELOCITY0x02 )
1030 {
1031 if (bytes_used + 4 > avail) {
1032 if (stopped != NULL((void*)0)) {
1033 *stopped = true1;
1034 }
1035 proto_item_set_len(item, bytes_used);
1036 return bytes_used;
1037 }
1038 /* Display the actual data set velocity feedback value */
1039 proto_tree_add_item(tree, hf_cip_act_vel, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
1040 bytes_used += 4;
1041 }
1042
1043 if ( (act_data_set & ACTUAL_DATA_SET_ACCELERATION0x04) == ACTUAL_DATA_SET_ACCELERATION0x04 )
1044 {
1045 if (bytes_used + 4 > avail) {
1046 if (stopped != NULL((void*)0)) {
1047 *stopped = true1;
1048 }
1049 proto_item_set_len(item, bytes_used);
1050 return bytes_used;
1051 }
1052 /* Display the actual data set acceleration feedback value */
1053 proto_tree_add_item(tree, hf_cip_act_accel, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000 );
1054 bytes_used += 4;
1055 }
1056
1057
1058 proto_item_set_len(item, bytes_used);
1059
1060 return bytes_used;
1061}
1062
1063/*
1064 * Function name: dissect_status_data_set
1065 *
1066 * Purpose: Dissect the "Cyclic Status Data" of a Device-to-Controller format message
1067 *
1068 * Based on the Status Data Set bits of the "Cyclic Actual Data Block" header, display
1069 * any of those status values.
1070 *
1071 * Returns: The number of bytes in the cyclic data used
1072 */
1073static uint32_t
1074dissect_status_data_set(uint32_t status_data_set, proto_tree* parent_tree, tvbuff_t* tvb, uint32_t offset, uint32_t avail)
1075{
1076 // If no Status Data Set bits are set, then we don't need to display any additional data.
1077 if (status_data_set == 0 || avail == 0)
1078 {
1079 return 0;
1080 }
1081
1082 uint32_t bytes_used = 0;
1083
1084 proto_item* item;
1085 proto_tree* tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0, ett_cyclic_command_data, &item, "Cyclic Status Data");
1086
1087 /* The order of these if statements is VERY important, this is the order the values will
1088 * appear in the cyclic data */
1089 if ( (status_data_set & STATUS_DATA_SET_AXIS_FAULT0x01) == STATUS_DATA_SET_AXIS_FAULT0x01 )
1090 {
1091 if (bytes_used + 12 > avail) {
1092 proto_item_set_len(item, bytes_used);
1093 return bytes_used;
1094 }
1095 /* Display the various fault codes from the device */
1096 proto_tree_add_item(tree, hf_cip_fault_type, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1097 bytes_used += 1;
1098
1099 proto_tree_add_item(tree, hf_cip_axis_fault, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1100 bytes_used += 1;
1101
1102 proto_tree_add_item(tree, hf_cip_fault_sub_code, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1103 bytes_used += 1;
1104
1105 proto_tree_add_item(tree, hf_cip_fault_action, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1106 bytes_used += 1;
1107
1108 proto_tree_add_item(tree, hf_cip_fault_time_stamp, tvb, offset + bytes_used, 8, ENC_LITTLE_ENDIAN0x80000000);
1109 bytes_used += 8;
1110 }
1111
1112 if ( (status_data_set & STATUS_DATA_SET_AXIS_ALARM0x02) == STATUS_DATA_SET_AXIS_ALARM0x02 )
1113 {
1114 if (bytes_used + 12 > avail) {
1115 proto_item_set_len(item, bytes_used);
1116 return bytes_used;
1117 }
1118 /* Display the various alarm codes from the device */
1119 proto_tree_add_item(tree, hf_cip_alarm_type, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1120 bytes_used += 1;
1121
1122 proto_tree_add_item(tree, hf_cip_axis_alarm, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1123 bytes_used += 1;
1124
1125 proto_tree_add_item(tree, hf_cip_alarm_sub_code, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1126 bytes_used += 1;
1127
1128 proto_tree_add_item(tree, hf_cip_alarm_state, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1129 bytes_used += 1;
1130
1131 proto_tree_add_item(tree, hf_cip_alarm_time_stamp, tvb, offset + bytes_used, 8, ENC_LITTLE_ENDIAN0x80000000);
1132 bytes_used += 8;
1133 }
1134
1135 if ( (status_data_set & STATUS_DATA_SET_AXIS_STATUS0x04) == STATUS_DATA_SET_AXIS_STATUS0x04 )
1136 {
1137 if (bytes_used + 8 > avail) {
1138 proto_item_set_len(item, bytes_used);
1139 return bytes_used;
1140 }
1141 /* Display the various axis state values from the device */
1142 bytes_used += dissect_axis_status(NULL((void*)0), tree, NULL((void*)0), tvb, offset + bytes_used, 4);
1143
1144 proto_tree_add_item(tree, hf_cip_axis_status_mfg, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1145 bytes_used += 4;
1146 }
1147
1148 if ( (status_data_set & STATUS_DATA_SET_AXIS_IO_STATUS0x08) == STATUS_DATA_SET_AXIS_IO_STATUS0x08 )
1149 {
1150 if (bytes_used + 8 > avail) {
1151 proto_item_set_len(item, bytes_used);
1152 return bytes_used;
1153 }
1154 proto_tree_add_item(tree, hf_cip_axis_io_status, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1155 bytes_used += 4;
1156
1157 proto_tree_add_item(tree, hf_cip_axis_io_status_mfg, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1158 bytes_used += 4;
1159 }
1160
1161 if ( (status_data_set & STATUS_DATA_SET_AXIS_SAFETY0x10) == STATUS_DATA_SET_AXIS_SAFETY0x10 )
1162 {
1163 if (bytes_used + 12 > avail) {
1164 proto_item_set_len(item, bytes_used);
1165 return bytes_used;
1166 }
1167 proto_tree_add_item(tree, hf_cip_axis_safety_status, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1168 bytes_used += 4;
1169 proto_tree_add_item(tree, hf_cip_axis_safety_status_mfg, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1170 bytes_used += 4;
1171 proto_tree_add_item(tree, hf_cip_axis_safety_state, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1172 bytes_used += 4;
1173 }
1174
1175 proto_item_set_len(item, bytes_used);
1176
1177 return bytes_used;
1178}
1179
1180/*
1181 * Function name: dissect_cntr_cyclic
1182 *
1183 * Purpose: Dissect the "Cyclic Command Data Block" of a Controller-to-Device format message
1184 *
1185 * Returns: The new offset into the message that follow on dissections should use
1186 * as their starting offset
1187 */
1188static uint32_t
1189dissect_cntr_cyclic(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1190{
1191 /* Create the tree for the entire instance data header */
1192 proto_tree* header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_cyclic_data_block, NULL((void*)0), "Cyclic Command Data Block");
1193
1194 /* The header is 8 bytes of the block. A shorter block used to read
1195 past size, and the return value followed the bits rather than size,
1196 so the next block started at the wrong offset. */
1197 if (size < 8) {
1198 proto_tree_add_item(header_tree, hf_cip_data, tvb, offset, size, ENC_NA0x00000000);
1199 return offset + size;
1200 }
1201
1202 proto_tree_add_item(header_tree, hf_cip_motor_cntrl, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1203 dissect_feedback_mode(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 1, 1);
1204 proto_tree_add_item(header_tree, hf_cip_axis_control, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1205 dissect_control_status(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 3, 1);
1206
1207 dissect_command_data_set_bits(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 4, 1);
1208 dissect_actual_data_set_bits(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 5, 1);
1209 dissect_status_data_set_bits(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 6, 1);
1210 dissect_command_control(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 7, 1);
1211
1212 uint32_t bytes_used = 8;
1213
1214 /* Determine if the dissector should be using an LREAL or DINT for position */
1215 uint8_t command_control = tvb_get_uint8(tvb, offset + 7);
1216 bool_Bool lreal_pos = ((command_control & COMMAND_CONTROL_POSITION_DATA_TYPE0x0C) == POSITION_DATA_LREAL0x00);
1217
1218 /* Cyclic Command Data: Display the command data values from the cyclic data payload, the
1219 * cyclic data starts immediately after the interpolation control field in the controller to device
1220 * direction */
1221 uint32_t command_data_set = tvb_get_uint8(tvb, offset + 4);
1222 bytes_used += dissect_cmd_data_set(command_data_set, header_tree, tvb, offset + bytes_used, lreal_pos, size - bytes_used);
Value stored to 'bytes_used' is never read
1223
1224 /* The following block starts after this one, not after the bits. */
1225 return offset + size;
1226}
1227
1228/*
1229 * Function name: dissect_device_cyclic
1230 *
1231 * Purpose: Dissect the "Cyclic Actual Data Block" of a Device-to-Controller format message
1232 *
1233 * Returns: The new offset into the message that follow on dissections should use
1234 * as their starting offset
1235 */
1236static uint32_t
1237dissect_device_cyclic(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1238{
1239 /* Create the tree for the entire instance data header */
1240 proto_tree* header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_cyclic_data_block, NULL((void*)0), "Cyclic Actual Data Block");
1241
1242 if (size < 8) {
1243 proto_tree_add_item(header_tree, hf_cip_data, tvb, offset, size, ENC_NA0x00000000);
1244 return offset + size;
1245 }
1246
1247 proto_tree_add_item(header_tree, hf_cip_motor_cntrl, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1248 dissect_feedback_mode(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 1, 1);
1249 proto_tree_add_item(header_tree, hf_cip_axis_response, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1250 proto_tree_add_item(header_tree, hf_cip_axis_resp_stat, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1251
1252 dissect_actual_data_set_bits(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 5, 1);
1253 dissect_status_data_set_bits(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 6, 1);
1254 proto_tree_add_item(header_tree, hf_cip_axis_state, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN0x80000000);
1255
1256 uint32_t bytes_used = 8;
1257
1258 /* Display the "Cyclic Actual Data" values from the cyclic data payload. */
1259 uint8_t feedback_mode = tvb_get_uint8(tvb, offset + 1);
1260 uint8_t actual_data_set = tvb_get_uint8(tvb, offset + 5);
1261 bool_Bool act_stopped = false0;
1262 bytes_used += dissect_act_data_set(actual_data_set, header_tree, tvb, offset + bytes_used, feedback_mode, size - bytes_used, &act_stopped);
1263
1264 /* Skip status when the actual-data bits did not fit: the leftover
1265 bytes are truncated actual data, not the status block. */
1266 if (!act_stopped) {
1267 uint8_t status_data_set = tvb_get_uint8(tvb, offset + 6);
1268 bytes_used += dissect_status_data_set(status_data_set, header_tree, tvb, offset + bytes_used, size - bytes_used);
1269 }
1270
1271 return offset + size;
1272}
1273
1274/*
1275 * Function name: dissect_cyclic_wt
1276 *
1277 * Purpose: Dissect the "Cyclic Write Data Block" in a Controller-to-Device message
1278 *
1279 * Returns: The new offset into the message that follow on dissections should use
1280 * as their starting offset
1281 */
1282static uint32_t
1283dissect_cyclic_wt(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1284{
1285 proto_tree *header_tree;
1286
1287 /* Create the tree for the entire cyclic write data block */
1288 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_cyclic_rd_wt, NULL((void*)0), "Cyclic Write Data Block");
1289
1290 /* Display the cyclic write block id value */
1291 proto_tree_add_item(header_tree, hf_cip_cyclic_write_blk, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1292
1293 /* Display the cyclic read block id value */
1294 proto_tree_add_item(header_tree, hf_cip_cyclic_read_blk, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1295
1296 /* Display the remainder of the cyclic write data if there is any */
1297 if ( size > 4 )
1298 {
1299 proto_tree_add_item(header_tree, hf_cip_cyclic_wrt_data, tvb, offset + 4, size - 4, ENC_NA0x00000000);
1300 }
1301
1302 return offset + size;
1303}
1304
1305/*
1306 * Function name: dissect_cyclic_rd
1307 *
1308 * Purpose: Dissect the "Cyclic Read Data Block" in a Device-to-Controller message
1309 *
1310 * Returns: The new offset into the message that follow on dissections should use
1311 * as their starting offset
1312 */
1313static uint32_t
1314dissect_cyclic_rd(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1315{
1316 proto_tree *header_tree;
1317
1318 /* Create the tree for the entire cyclic write data block */
1319 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_cyclic_rd_wt, NULL((void*)0), "Cyclic Read Data Block");
1320
1321 /* Display the cyclic write block id value */
1322 proto_tree_add_item(header_tree, hf_cip_cyclic_write_blk, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1323
1324 /* Display the cyclic write status value */
1325 proto_tree_add_item(header_tree, hf_cip_cyclic_write_sts, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN0x80000000);
1326
1327 /* Display the cyclic read block id value */
1328 proto_tree_add_item(header_tree, hf_cip_cyclic_read_blk, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1329
1330 /* Display the cyclic read status value */
1331 proto_tree_add_item(header_tree, hf_cip_cyclic_read_sts, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1332
1333 /* Display the remainder of the cyclic read data if there is any*/
1334 if ( size > 4 )
1335 {
1336 proto_tree_add_item(header_tree, hf_cip_cyclic_rd_data, tvb, offset + 4, size - 4, ENC_NA0x00000000);
1337 }
1338
1339 return offset + size;
1340}
1341
1342/*
1343 * Function name: dissect_cntr_event
1344 *
1345 * Purpose: Dissect the "Event Data Block" in a Controller-to-Device message
1346 *
1347 * Returns: The new offset into the message that follow on dissections should use
1348 * as their starting offset
1349 */
1350static uint32_t
1351dissect_cntr_event(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1352{
1353 proto_tree *header_tree;
1354 uint32_t acks, cur_ack;
1355 uint32_t bytes_used = 0;
1356
1357 /* Create the tree for the entire cyclic write data block */
1358 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_event, NULL((void*)0), "Event Data Block");
1359
1360 uint32_t event_checking_control = tvb_get_letohl(tvb, offset);
1361 dissect_event_checking_control(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset, 4);
1362
1363 /* The event checking control value is 4 bytes long */
1364 bytes_used = 4;
1365
1366 /* Bits 30..28. Bit 31 is the extended format and is not dissected.
1367 The displayed count uses the same 3-bit mask. */
1368 acks = (event_checking_control >> 28) & 0x07;
1369
1370 /* Each acknowledgement contains and id and a status value */
1371 for (cur_ack = 0; cur_ack < acks; cur_ack++)
1372 {
1373 if (bytes_used + 2 > size) {
1374 break;
1375 }
1376 /* Display the current acknowledgement id */
1377 proto_tree_add_item(header_tree, hf_cip_event_ack, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1378 bytes_used += 1;
1379
1380 /* Display the current event status */
1381 proto_tree_add_item(header_tree, hf_cip_evnt_sts_stat, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1382 bytes_used += 1;
1383 }
1384
1385 return offset + size;
1386}
1387
1388/*
1389 * Function name: dissect_devce_event
1390 *
1391 * Purpose: Dissect the "Event Data Block" in a Device-to-Controller message
1392 *
1393 * Returns: The new offset into the message that follow on dissections should use
1394 * as their starting offset
1395 */
1396static uint32_t
1397dissect_devce_event(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1398{
1399 proto_tree *header_tree;
1400 uint64_t nots, cur_not;
1401 uint32_t bytes_used = 0;
1402
1403 /* Create the tree for the entire cyclic write data block */
1404 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_event, NULL((void*)0), "Event Data Block");
1405
1406 uint32_t event_checking_status = tvb_get_letohl(tvb, offset);
1407 dissect_event_checking_status(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset, 4);
1408
1409 /* The event status control value is 4 bytes long */
1410 bytes_used = 4;
1411
1412 /* Bits 30..28. Bit 31 is the extended format and is not dissected. */
1413 nots = (event_checking_status >> 28) & 0x07;
1414
1415 /* Each notification contains and id, status value, event type, position and time stamp */
1416 for (cur_not = 0; cur_not < nots; cur_not++)
1417 {
1418 /* id, status, type+reserved, position, timestamp: 16 bytes */
1419 if (bytes_used + 16 > size) {
1420 break;
1421 }
1422 /* Display the current event id */
1423 proto_tree_add_item(header_tree, hf_cip_event_id, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1424 bytes_used += 1;
1425
1426 /* Display the current event status */
1427 proto_tree_add_item(header_tree, hf_cip_evnt_sts_stat, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1428 bytes_used += 1;
1429
1430 /* Display the current event type */
1431 proto_tree_add_item(header_tree, hf_cip_evnt_type, tvb, offset + bytes_used, 1, ENC_LITTLE_ENDIAN0x80000000);
1432 bytes_used += 2; /* Increment by 2 to jump the reserved byte */
1433
1434 /* Display the event position value */
1435 proto_tree_add_item(header_tree, hf_cip_event_pos, tvb, offset + bytes_used, 4, ENC_LITTLE_ENDIAN0x80000000);
1436 bytes_used += 4;
1437
1438 /* Display the event time stamp value */
1439 proto_tree_add_item(header_tree, hf_cip_event_ts, tvb, offset + bytes_used, 8, ENC_LITTLE_ENDIAN0x80000000);
1440 bytes_used += 8;
1441 }
1442
1443 return size + offset;
1444}
1445
1446/*
1447 * Function name: dissect_get_axis_attr_list_request
1448 *
1449 * Purpose: Dissect the get axis attribute list service request
1450 *
1451 * Returns: None
1452 */
1453static void
1454dissect_get_axis_attr_list_request(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1455{
1456 proto_item *attr_item;
1457 proto_tree *header_tree, *attr_tree;
1458 uint32_t local_offset;
1459
1460 /* Create the tree for the get axis attribute list request */
1461 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL((void*)0), "Get Axis Attribute List Request");
1462
1463 /* Read the number of attributes that are contained within the request */
1464 uint32_t attribute_cnt;
1465 proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1466
1467 /* Start the attribute loop at the beginning of the first attribute in the list */
1468 local_offset = offset + 4;
1469
1470 /* For each attribute display the associated fields */
1471 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1472 {
1473 /* At a minimum the local offset needs will need to be incremented by 4 bytes to reach the next attribute */
1474 uint8_t increment_size = 4;
1475
1476 /* Create the tree for this attribute within the request */
1477 uint32_t attribute_id;
1478 attr_item = proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1479 attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
1480
1481 uint32_t dimension;
1482 proto_tree_add_item_ret_uint(attr_tree, hf_get_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000, &dimension);
1483 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1484
1485 if (dimension == 1)
1486 {
1487 /* Display the start index and start index from the request */
1488 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN0x80000000);
1489 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN0x80000000);
1490
1491 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1492 increment_size += 4;
1493 }
1494
1495 const attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION0x42, instance_id, attribute_id);
1496 if (pattribute != NULL((void*)0))
1497 {
1498 proto_item_append_text(attr_item, " (%s)", pattribute->text);
1499 }
1500
1501 /* Move the local offset to the next attribute */
1502 local_offset += increment_size;
1503 }
1504}
1505
1506static unsigned dissect_motion_attribute(packet_info *pinfo, tvbuff_t* tvb, int offset, uint32_t attribute_id,
1507 uint32_t instance_id, proto_item* attr_item, proto_tree* attr_tree, uint8_t dimension, uint32_t attribute_size)
1508{
1509 const attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION0x42, instance_id, attribute_id);
1510 int parsed_len = 0;
1511
1512 if (pattribute != NULL((void*)0))
1513 {
1514 proto_item_append_text(attr_item, " (%s)", pattribute->text);
1515
1516 // TODO: Handle more dimensions. Unsure about the format when there is more than 1 item.
1517 if (dimension <= 1)
1518 {
1519 parsed_len = dissect_cip_attribute(pinfo, attr_tree, attr_item, tvb, pattribute, offset, attribute_size);
1520 }
1521 }
1522
1523 return parsed_len;
1524}
1525
1526/*
1527 * Function name: dissect_set_axis_attr_list_request
1528 *
1529 * Purpose: Dissect the set axis attribute list service request
1530 *
1531 * Returns: None
1532 */
1533static void
1534dissect_set_axis_attr_list_request(packet_info *pinfo, tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1535{
1536 proto_item *attr_item;
1537 proto_tree *header_tree, *attr_tree;
1538 uint32_t local_offset;
1539
1540 /* Create the tree for the set axis attribute list request */
1541 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_set_axis_attribute, NULL((void*)0), "Set Axis Attribute List Request");
1542
1543 /* Read the number of attributes that are contained within the request */
1544 uint32_t attribute_cnt;
1545 proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1546
1547 /* Start the attribute loop at the beginning of the first attribute in the list */
1548 local_offset = offset + 4;
1549
1550 /* For each attribute display the associated fields */
1551 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1552 {
1553 /* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
1554 uint8_t increment_size = 4;
1555
1556 /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
1557 * properly displaying of the attribute is possible */
1558 uint8_t attribute_start = 4;
1559
1560 /* Create the tree for this attribute in the get axis attribute list request */
1561 uint32_t attribute_id;
1562 attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1563 attr_tree = proto_item_add_subtree(attr_item, ett_set_axis_attr_list);
1564
1565 uint32_t dimension;
1566 proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000, &dimension);
1567
1568 uint32_t attribute_size;
1569 proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000, &attribute_size);
1570
1571 if (dimension == 1)
1572 {
1573 uint32_t data_elements;
1574
1575 /* Display the start index and start index from the request if the request is an array */
1576 proto_tree_add_item(attr_tree, hf_set_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN0x80000000);
1577 proto_tree_add_item_ret_uint(attr_tree, hf_set_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN0x80000000, &data_elements);
1578
1579 /* Modify the size of the attribute data by the number of elements if the request is an array request */
1580 attribute_size *= data_elements;
1581
1582 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1583 increment_size += 4;
1584 attribute_start += 4;
1585 }
1586
1587 unsigned parsed_len = dissect_motion_attribute(pinfo, tvb, local_offset + attribute_start, attribute_id,
1588 instance_id, attr_item, attr_tree, dimension, attribute_size);
1589
1590 // Display the raw attribute data if configured. Otherwise, just show the remaining unparsed data.
1591 if (display_full_attribute_data)
1592 {
1593 proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start, attribute_size, ENC_NA0x00000000);
1594 }
1595 else if (attribute_size > parsed_len)
1596 {
1597 proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start + parsed_len, attribute_size - parsed_len, ENC_NA0x00000000);
1598 }
1599
1600 /* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
1601 attribute_size = WS_ROUNDUP_4(attribute_size)(((attribute_size) + ((unsigned)(4U-1U))) & (~((unsigned)
(4U-1U))))
;
1602
1603 /* Move the local offset to the next attribute */
1604 local_offset += (attribute_size + increment_size);
1605 }
1606}
1607
1608/*
1609 * Function name: dissect_group_sync_request
1610 *
1611 * Purpose: Dissect the group sync service request
1612 *
1613 * Returns: None
1614 */
1615static void
1616dissect_group_sync_request (tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size)
1617{
1618 proto_tree *header_tree;
1619
1620 /* Create the tree for the group sync request */
1621 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_group_sync, NULL((void*)0), "Group Sync Request");
1622
1623 /* Read the grandmaster id from the payload */
1624 proto_tree_add_item(header_tree, hf_cip_ptp_grandmaster, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
1625}
1626
1627static void dissect_set_cyclic_list_request(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id, const char* service_name)
1628{
1629 proto_tree* header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_set_cyclic_list, NULL((void*)0), service_name);
1630
1631 uint32_t attribute_cnt;
1632 proto_tree_add_item_ret_uint(header_tree, hf_set_cyclic_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1633
1634 // Skip Number of Attributes and Reserved field.
1635 offset += 4;
1636
1637 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1638 {
1639 uint32_t attribute_id;
1640 proto_item* attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_cyclic_list_attribute_id, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1641
1642 const attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION0x42, instance_id, attribute_id);
1643 if (pattribute != NULL((void*)0))
1644 {
1645 proto_item_append_text(attr_item, " (%s)", pattribute->text);
1646 }
1647
1648 offset += 2;
1649 }
1650}
1651
1652static void dissect_set_cyclic_list_respone(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id, const char* service_name)
1653{
1654 proto_tree* header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_set_cyclic_list, NULL((void*)0), service_name);
1655
1656 uint32_t attribute_cnt;
1657 proto_tree_add_item_ret_uint(header_tree, hf_set_cyclic_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1658
1659 proto_tree_add_item(header_tree, hf_set_cyclic_list_read_block_id, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN0x80000000);
1660
1661 // Skip Number of Attributes and Cyclic Read Block ID field.
1662 offset += 4;
1663
1664 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1665 {
1666 uint32_t attribute_id;
1667 proto_item* attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_cyclic_list_attribute_id, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1668
1669 const attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION0x42, instance_id, attribute_id);
1670 if (pattribute != NULL((void*)0))
1671 {
1672 proto_item_append_text(attr_item, " (%s)", pattribute->text);
1673 }
1674
1675 offset += 2;
1676
1677 proto_tree_add_item(header_tree, hf_set_cyclic_list_attr_sts, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1678
1679 // Skip over Attribute Status and Reserved field.
1680 offset += 2;
1681 }
1682}
1683
1684/*
1685 * Function name: dissect_cntr_service
1686 *
1687 * Purpose: Dissect the "Service Data Block" in a Controller-to-Device message
1688 *
1689 * Returns: The new offset into the message that follow on dissections should use
1690 * as their starting offset
1691 */
1692static uint32_t
1693dissect_cntr_service(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1694{
1695 proto_tree *header_tree;
1696 uint32_t service;
1697
1698 /* Create the tree for the entire service data block */
1699 proto_item *item;
1700 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_service, &item, "Service Data Block");
1701
1702 /* Display the transaction id value */
1703 proto_tree_add_item(header_tree, hf_cip_svc_transction, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1704
1705 /* Display the service code */
1706 proto_tree_add_item_ret_uint(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN0x80000000, &service);
1707
1708 /* If the service is a set axis, get axis attribute or group sync request dissect it as well */
1709 if (size > 4)
1710 {
1711 switch (service)
1712 {
1713 case SC_GET_AXIS_ATTRIBUTE_LIST0x4B:
1714 dissect_get_axis_attr_list_request(tvb, header_tree, offset + 4, size - 4, instance_id);
1715 break;
1716 case SC_SET_AXIS_ATTRIBUTE_LIST0x4C:
1717 dissect_set_axis_attr_list_request(pinfo, tvb, header_tree, offset + 4, size - 4, instance_id);
1718 break;
1719 case SC_GROUP_SYNC0x1C:
1720 dissect_group_sync_request(tvb, header_tree, offset + 4, size - 4);
1721 break;
1722 case SC_SET_CYCLIC_WRITE_LIST0x4D:
1723 dissect_set_cyclic_list_request(tvb, header_tree, offset + 4, size - 4, instance_id, "Set Cyclic Write List Request");
1724 break;
1725 case SC_SET_CYCLIC_READ_LIST0x4E:
1726 dissect_set_cyclic_list_request(tvb, header_tree, offset + 4, size - 4, instance_id, "Set Cyclic Read List Request");
1727 break;
1728 case SC_SET_ATT_LIST0x04:
1729 {
1730 cip_simple_request_info_t motion_path;
1731 motion_path.iClass = CI_CLS_MOTION0x42;
1732 motion_path.iInstance = instance_id;
1733
1734 tvbuff_t* tvb_set_attr = tvb_new_subset_length(tvb, offset + 4, size - 4);
1735 int parsed_len = dissect_cip_set_attribute_list_req(tvb_set_attr, pinfo, header_tree, item, 0, &motion_path);
1736
1737 // Display any remaining unparsed data.
1738 int remain_len = tvb_reported_length_remaining(tvb, offset + 4 + parsed_len);
1739 if (remain_len > 0)
1740 {
1741 proto_tree_add_item(header_tree, hf_cip_attribute_data, tvb, offset + 4 + parsed_len, size - 4 - parsed_len, ENC_NA0x00000000);
1742 }
1743
1744 break;
1745 }
1746 default:
1747 /* Display the remainder of the service channel data */
1748 proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA0x00000000);
1749 }
1750 }
1751
1752 return offset + size;
1753}
1754
1755/*
1756 * Function name: dissect_set_axis_attr_list_response
1757 *
1758 * Purpose: Dissect the set axis attribute list service response
1759 *
1760 * Returns: None
1761 */
1762static void
1763dissect_set_axis_attr_list_response(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1764{
1765 proto_item *attr_item;
1766 proto_tree *header_tree, *attr_tree;
1767 uint32_t local_offset;
1768
1769 /* Create the tree for the set axis attribute list response */
1770 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL((void*)0), "Set Axis Attribute List Response");
1771
1772 /* Read the number of attributes that are contained within the response */
1773 uint32_t attribute_cnt;
1774 proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1775
1776 /* Start the attribute loop at the beginning of the first attribute in the list */
1777 local_offset = offset + 4;
1778
1779 /* For each attribute display the associated fields */
1780 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1781 {
1782 /* Create the tree for the current attribute in the set axis attribute list response */
1783 uint32_t attribute_id;
1784 attr_item = proto_tree_add_item_ret_uint(header_tree, hf_set_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1785 attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
1786
1787 /* Add the response status to the tree */
1788 proto_tree_add_item(attr_tree, hf_cip_svc_set_axis_attr_sts, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1789
1790 const attribute_info_t* pattribute = cip_get_attribute(CI_CLS_MOTION0x42, instance_id, attribute_id);
1791 if (pattribute != NULL((void*)0))
1792 {
1793 proto_item_append_text(attr_item, " (%s)", pattribute->text);
1794 }
1795
1796 /* Move the local offset to the next attribute */
1797 local_offset += 4;
1798 }
1799}
1800
1801/*
1802 * Function name: dissect_get_axis_attr_list_response
1803 *
1804 * Purpose: Dissect the get axis attribute list service response
1805 *
1806 * Returns: None
1807 */
1808static void
1809dissect_get_axis_attr_list_response(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1810{
1811 proto_item *attr_item;
1812 proto_tree *header_tree, *attr_tree;
1813 uint32_t local_offset;
1814
1815 /* Create the tree for the get axis attribute list response */
1816 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_get_axis_attribute, NULL((void*)0), "Get Axis Attribute List Response");
1817
1818 /* Read the number of attributes that are contained within the request */
1819 uint32_t attribute_cnt;
1820 proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_cnt, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_cnt);
1821
1822 /* Start the attribute loop at the beginning of the first attribute in the list */
1823 local_offset = offset + 4;
1824
1825 /* For each attribute display the associated fields */
1826 for (uint32_t attribute = 0; attribute < attribute_cnt; attribute++)
1827 {
1828 /* At a minimum the local offset needs to be incremented by 4 bytes to reach the next attribute */
1829 uint8_t increment_size = 4;
1830
1831 /* Pull the fields for this attribute from the payload, all fields are needed to make some calculations before
1832 * properly displaying of the attribute is possible */
1833 uint8_t dimension = tvb_get_uint8(tvb, local_offset + 2);
1834 uint32_t attribute_size = tvb_get_uint8(tvb, local_offset + 3);
1835 uint8_t attribute_start = 4;
1836
1837 if (dimension == 1)
1838 {
1839 uint16_t data_elements = tvb_get_letohs(tvb, local_offset + 6);
1840
1841 /* Modify the size of the attribute data by the number of elements if the request is an array request */
1842 attribute_size *= data_elements;
1843
1844 /* Modify the amount to update the local offset by and the start of the data to include the index and elements field */
1845 increment_size += 4;
1846 attribute_start += 4;
1847 }
1848
1849 /* Display the fields associated with the get axis attribute list response */
1850 uint32_t attribute_id;
1851 attr_item = proto_tree_add_item_ret_uint(header_tree, hf_get_axis_attr_list_attribute_id, tvb, local_offset, 2, ENC_LITTLE_ENDIAN0x80000000, &attribute_id);
1852 attr_tree = proto_item_add_subtree(attr_item, ett_get_axis_attr_list);
1853
1854 if (dimension == 0xFF)
1855 {
1856 /* Display the element size as an error code if the dimension field indicates an error */
1857 proto_tree_add_item(attr_tree, hf_cip_svc_get_axis_attr_sts, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1858
1859 /* No attribute data so no attribute size */
1860 attribute_size = 0;
1861 }
1862 else
1863 {
1864 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_dimension, tvb, local_offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1865 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_element_size, tvb, local_offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1866
1867 if (dimension == 1)
1868 {
1869 /* Display the start index and start index from the request */
1870 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_start_index, tvb, local_offset + 4, 2, ENC_LITTLE_ENDIAN0x80000000);
1871 proto_tree_add_item(attr_tree, hf_get_axis_attr_list_data_elements, tvb, local_offset + 6, 2, ENC_LITTLE_ENDIAN0x80000000);
1872 }
1873
1874 unsigned parsed_len = dissect_motion_attribute(pinfo, tvb, local_offset + attribute_start, attribute_id,
1875 instance_id, attr_item, attr_tree, dimension, attribute_size);
1876
1877 // Display the raw attribute data if configured. Otherwise, just show the remaining unparsed data
1878 if (display_full_attribute_data)
1879 {
1880 proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start, attribute_size, ENC_NA0x00000000);
1881 }
1882 else if (attribute_size > parsed_len)
1883 {
1884 proto_tree_add_item(attr_tree, hf_cip_attribute_data, tvb, local_offset + attribute_start + parsed_len, attribute_size - parsed_len, ENC_NA0x00000000);
1885 }
1886
1887 /* Round the attribute size up so the next attribute lines up on a 32-bit boundary */
1888 attribute_size = WS_ROUNDUP_4(attribute_size)(((attribute_size) + ((unsigned)(4U-1U))) & (~((unsigned)
(4U-1U))))
;
1889 }
1890
1891 /* Move the local offset to the next attribute */
1892 local_offset += (attribute_size + increment_size);
1893 }
1894}
1895
1896/*
1897 * Function name: dissect_group_sync_response
1898 *
1899 * Purpose: Dissect the group sync service response
1900 *
1901 * Returns: None
1902 */
1903static void
1904dissect_group_sync_response (tvbuff_t* tvb, proto_tree* tree, uint32_t offset)
1905{
1906 proto_tree_add_item(tree, hf_cip_group_sync, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1907}
1908
1909/*
1910 * Function name: dissect_devce_service
1911 *
1912 * Purpose: Dissect the "Service Data Block" in a Device-to-Controller message
1913 *
1914 * Returns: The new offset into the message that follow on dissections should use
1915 * as their starting offset
1916 */
1917static uint32_t
1918dissect_devce_service(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint32_t offset, uint32_t size, uint32_t instance_id)
1919{
1920 proto_tree *header_tree;
1921
1922 /* Create the tree for the entire service data block */
1923 proto_item* item;
1924 header_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_service, &item, "Service Data Block");
1925
1926 /* Display the transaction id value */
1927 proto_tree_add_item(header_tree, hf_cip_svc_transction, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
1928
1929 /* Display the service code */
1930 uint32_t service_code;
1931 proto_tree_add_item_ret_uint(header_tree, hf_cip_svc_code, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN0x80000000, &service_code);
1932
1933 /* Display the general status code */
1934 proto_tree_add_item(header_tree, hf_cip_svc_sts, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
1935
1936 /* Display the extended status code */
1937 proto_tree_add_item(header_tree, hf_cip_svc_ext_status, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN0x80000000);
1938
1939 /* If the service is a set axis, get axis attribute response or group sync dissect it as well */
1940 if (size > 4)
1941 {
1942 switch (service_code)
1943 {
1944 case SC_GET_AXIS_ATTRIBUTE_LIST0x4B:
1945 dissect_get_axis_attr_list_response(pinfo, tvb, header_tree, offset + 4, size - 4, instance_id);
1946 break;
1947 case SC_SET_AXIS_ATTRIBUTE_LIST0x4C:
1948 dissect_set_axis_attr_list_response(tvb, header_tree, offset + 4, size - 4, instance_id);
1949 break;
1950 case SC_GROUP_SYNC0x1C:
1951 dissect_group_sync_response(tvb, header_tree, offset + 4);
1952 break;
1953 case SC_SET_CYCLIC_WRITE_LIST0x4D:
1954 dissect_set_cyclic_list_respone(tvb, header_tree, offset + 4, size - 4, instance_id, "Set Cyclic Write List Response");
1955 break;
1956 case SC_SET_CYCLIC_READ_LIST0x4E:
1957 dissect_set_cyclic_list_respone(tvb, header_tree, offset + 4, size - 4, instance_id, "Set Cyclic Read List Response");
1958 break;
1959 case SC_SET_ATT_LIST0x04:
1960 {
1961 cip_simple_request_info_t motion_path;
1962 motion_path.iClass = CI_CLS_MOTION0x42;
1963 motion_path.iInstance = instance_id;
1964
1965 tvbuff_t* tvb_set_attr = tvb_new_subset_length(tvb, offset + 4, size - 4);
1966 dissect_cip_set_attribute_list_rsp(tvb_set_attr, pinfo, header_tree, item, 0, &motion_path);
1967 break;
1968 }
1969 default:
1970 /* Display the remainder of the service channel data */
1971 proto_tree_add_item(header_tree, hf_cip_svc_data, tvb, offset + 4, size - 4, ENC_NA0x00000000);
1972 break;
1973 }
1974 }
1975
1976 return offset + size;
1977}
1978
1979/*
1980 * Function name: dissect_var_inst_header
1981 *
1982 * Purpose: Dissect the instance data header of a variable controller to device or
1983 * device to controller message
1984 *
1985 * Returns: void
1986 */
1987static void
1988dissect_var_inst_header(tvbuff_t* tvb, proto_tree* tree, uint32_t offset, uint8_t* inst_number, uint32_t* cyc_size,
1989 uint32_t* cyc_blk_size, uint32_t* evnt_size, uint32_t* servc_size)
1990{
1991 proto_tree *header_tree;
1992
1993 /* Create the tree for the entire instance data header */
1994 *inst_number = tvb_get_uint8(tvb, offset);
1995
1996 header_tree = proto_tree_add_subtree_format(tree, tvb, offset, 8, ett_inst_data_header, NULL((void*)0),
1997 "Instance Data Header - Instance: %d", *inst_number);
1998
1999 /* Read the instance number field from the instance data header */
2000 proto_tree_add_item(header_tree, hf_var_devce_instance, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2001
2002 /* The "size" fields in the instance data block header are all stored as number of 32-bit words the
2003 * block uses since all blocks should pad up to 32-bits so to convert to bytes each is multiplied by 4 */
2004
2005 /* Read the instance block size field in bytes from the instance data header */
2006 proto_tree_add_item(header_tree, hf_var_devce_instance_block_size, tvb, offset + 2, 1, ENC_NA0x00000000);
2007
2008 /* Read the cyclic block size field in bytes from the instance data header */
2009 proto_tree_add_item(header_tree, hf_var_devce_cyclic_block_size, tvb, offset + 3, 1, ENC_NA0x00000000);
2010
2011 /* Read the cyclic command block size field in bytes from the instance data header */
2012 *cyc_size = (tvb_get_uint8(tvb, offset + 4) * 4);
2013 proto_tree_add_item(header_tree, hf_var_devce_cyclic_data_block_size, tvb, offset + 4, 1, ENC_NA0x00000000);
2014
2015 /* Read the cyclic write block size field in bytes from the instance data header */
2016 *cyc_blk_size = (tvb_get_uint8(tvb, offset + 5) * 4);
2017 proto_tree_add_item(header_tree, hf_var_devce_cyclic_rw_block_size, tvb, offset + 5, 1, ENC_NA0x00000000);
2018
2019 /* Read the event block size in bytes from the instance data header */
2020 *evnt_size = (tvb_get_uint8(tvb, offset + 6) * 4);
2021 proto_tree_add_item(header_tree, hf_var_devce_event_block_size, tvb, offset + 6, 1, ENC_NA0x00000000);
2022
2023 /* Read the service block size in bytes from the instance data header */
2024 *servc_size = (tvb_get_uint8(tvb, offset + 7) * 4);
2025 proto_tree_add_item(header_tree, hf_var_devce_service_block_size, tvb, offset + 7, 1, ENC_NA0x00000000);
2026}
2027
2028/*
2029 * Function name: dissect_var_cont_conn_header
2030 *
2031 * Purpose: Dissect the connection header of a variable controller to device message
2032 *
2033 * Returns: Offset to the start of the instance data block
2034 */
2035static uint32_t
2036dissect_var_cont_conn_header(tvbuff_t* tvb, proto_tree* tree, uint32_t* inst_count, uint32_t offset)
2037{
2038 uint32_t header_size;
2039 proto_tree *header_tree;
2040
2041 /* Calculate the header size, start with the basic header size */
2042 header_size = 8;
2043
2044 uint32_t time_data_set = tvb_get_uint8(tvb, offset + 7);
2045
2046 /* Check the time data set field for enabled bits. If either update period or
2047 * update time stamp fields are set, bump the header size by the appropriate size */
2048 if ( (time_data_set & TIME_DATA_SET_TIME_STAMP0x1) == TIME_DATA_SET_TIME_STAMP0x1 )
2049 {
2050 header_size += 8;
2051 }
2052 if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET0x2) == TIME_DATA_SET_TIME_OFFSET0x2 )
2053 {
2054 header_size += 8;
2055 }
2056
2057 /* Create the tree for the entire connection header */
2058 header_tree = proto_tree_add_subtree(tree, tvb, offset, header_size, ett_cont_dev_header, NULL((void*)0), "Connection Header");
2059
2060 /* Add the connection header fields that are common to all types of messages */
2061 proto_tree_add_item(header_tree, hf_cip_format, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2062 proto_tree_add_item(header_tree, hf_cip_revision, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN0x80000000);
2063 proto_tree_add_item(header_tree, hf_cip_updateid, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
2064
2065 dissect_node_control(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 3, 1);
2066
2067 /* Add the instance count and last update id to the connection header tree */
2068 proto_tree_add_item_ret_uint(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN0x80000000, inst_count);
2069 proto_tree_add_item(header_tree, hf_cip_last_update, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN0x80000000);
2070
2071 dissect_time_data_set(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 7, 1);
2072
2073 /* Move the offset to the byte just beyond the time data set field */
2074 offset = (offset + 7 + 1);
2075
2076 /* Add the time values if they are present in the time data set header field */
2077 if ( (time_data_set & TIME_DATA_SET_TIME_STAMP0x1) == TIME_DATA_SET_TIME_STAMP0x1 )
2078 {
2079 proto_tree_add_item(header_tree, hf_cip_cont_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2080 offset = (offset + 8);
2081 }
2082
2083 if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET0x2) == TIME_DATA_SET_TIME_OFFSET0x2 )
2084 {
2085 proto_tree_add_item(header_tree, hf_cip_cont_time_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2086 offset = (offset + 8);
2087 }
2088
2089 /* Return the number of bytes used so it can be used as an offset in the following dissections */
2090 return offset;
2091}
2092
2093/*
2094 * Function name: dissect_var_devce_conn_header
2095 *
2096 * Purpose: Dissect the connection header of a variable device to controller message
2097 *
2098 * Returns: Offset to the start of the instance data block
2099 */
2100static uint32_t
2101dissect_var_devce_conn_header(tvbuff_t* tvb, proto_tree* tree, uint32_t* inst_count, uint32_t offset)
2102{
2103 uint32_t header_size;
2104 proto_tree *header_tree;
2105
2106 /* Calculate the header size, start with the basic header size */
2107 header_size = 8;
2108
2109 uint32_t time_data_set = tvb_get_uint8(tvb, offset + 7);
2110 if ( (time_data_set & TIME_DATA_SET_TIME_STAMP0x1) == TIME_DATA_SET_TIME_STAMP0x1 )
2111 {
2112 header_size += 8;
2113 }
2114 if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET0x2) == TIME_DATA_SET_TIME_OFFSET0x2 )
2115 {
2116 header_size += 8;
2117 }
2118 if ( (time_data_set & TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4) == TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4 )
2119 {
2120 header_size += 4;
2121 }
2122 if ( (time_data_set & TIME_DATA_SET_TIME_DIAGNOSTICS0x8) == TIME_DATA_SET_TIME_DIAGNOSTICS0x8 )
2123 {
2124 header_size += 16;
2125 }
2126
2127 /* Create the tree for the entire connection header */
2128 header_tree = proto_tree_add_subtree(tree, tvb, offset, header_size, ett_cont_dev_header, NULL((void*)0), "Connection Header");
2129
2130 /* Add the connection header fields that are common to all types of messages */
2131 proto_tree_add_item(header_tree, hf_cip_format, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2132 proto_tree_add_item(header_tree, hf_cip_revision, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN0x80000000);
2133 proto_tree_add_item(header_tree, hf_cip_updateid, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN0x80000000);
2134
2135 dissect_node_status(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 3, 1);
2136
2137 /* Add the instance count to the connection header tree */
2138 proto_tree_add_item_ret_uint(header_tree, hf_cip_instance_cnt, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN0x80000000, inst_count);
2139
2140 /* The device to controller header contains the node alarms and node faults fields as well. */
2141 proto_tree_add_item(header_tree, hf_cip_node_fltalarms, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN0x80000000);
2142
2143 /* Add the last update id to the connection header tree */
2144 proto_tree_add_item(header_tree, hf_cip_last_update, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN0x80000000);
2145
2146 dissect_time_data_set(NULL((void*)0), header_tree, NULL((void*)0), tvb, offset + 7, 1);
2147
2148 /* Move the offset to the byte just beyond the time data set field */
2149 offset = (offset + 7 + 1);
2150
2151 /* Add the time values if they are present in the time data set header field */
2152 if ( (time_data_set & TIME_DATA_SET_TIME_STAMP0x1) == TIME_DATA_SET_TIME_STAMP0x1 )
2153 {
2154 proto_tree_add_item(header_tree, hf_cip_devc_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2155 offset = (offset + 8);
2156 }
2157
2158 if ( (time_data_set & TIME_DATA_SET_TIME_OFFSET0x2) == TIME_DATA_SET_TIME_OFFSET0x2 )
2159 {
2160 proto_tree_add_item(header_tree, hf_cip_devc_time_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2161 offset = (offset + 8);
2162 }
2163
2164 if ( (time_data_set & TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4) == TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4 )
2165 {
2166 /* If the time diagnostic bit is set then the header contains the count of lost updates, late updates, data
2167 * received time stamp and data transmit time stamp */
2168 proto_tree_add_item(header_tree, hf_cip_lost_update, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2169 offset = (offset + 1);
2170
2171 /* Add the reserved bytes to the offset after adding the late updates to the display */
2172 proto_tree_add_item(header_tree, hf_cip_late_update, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2173 offset = (offset + 3);
2174 }
2175
2176 if ( (time_data_set & TIME_DATA_SET_TIME_DIAGNOSTICS0x8) == TIME_DATA_SET_TIME_DIAGNOSTICS0x8 )
2177 {
2178 proto_tree_add_item(header_tree, hf_cip_data_rx_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2179 offset += 8;
2180
2181 proto_tree_add_item(header_tree, hf_cip_data_tx_time_stamp, tvb, offset, 8, ENC_LITTLE_ENDIAN0x80000000);
2182 offset += 8;
2183 }
2184
2185 /* Return the number of bytes used so it can be used as an offset in the following dissections */
2186 return offset;
2187}
2188
2189
2190/*
2191 * Function name: dissect_cipmotion
2192 *
2193 * Purpose: Perform the top level dissection of the CIP Motion datagram, it is called by
2194 * Wireshark when the dissection rule registered in proto_reg_handoff_cipmotion is fired
2195 *
2196 * Returns: void
2197 */
2198static int
2199dissect_cipmotion(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
2200{
2201 cip_io_data_input* io_data_input = (cip_io_data_input*)data;
2202
2203 uint32_t con_format;
2204 uint32_t update_id;
2205 proto_item *proto_item_top;
2206 proto_tree *proto_tree_top;
2207 uint32_t offset = 0;
2208
2209 uint8_t ConnPoint = 2;
2210 if (io_data_input && io_data_input->conn_info)
2211 {
2212 ConnPoint = io_data_input->conn_info->connection_path.iConnPoint;
2213 }
2214
2215 /* Create display subtree for the protocol by creating an item and then
2216 * creating a subtree from the item, the subtree must have been registered
2217 * in proto_register_cipmotion already */
2218 proto_item_top = proto_tree_add_item(tree, proto_cipmotion, tvb, 0, -1, ENC_NA0x00000000);
2219 proto_tree_top = proto_item_add_subtree(proto_item_top, ett_cipmotion);
2220
2221 /* Add the CIP class 1 sequence number to the tree */
2222 proto_tree_add_item(proto_tree_top, hf_cip_class1_seqnum, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
2223 offset = (offset + 2);
2224
2225 if (ConnPoint >= 3)
2226 {
2227 dissect_cip_run_idle(tvb, offset, proto_tree_top);
2228 offset += 4;
2229 }
2230
2231 /* Pull the actual values for the connection format and update id from the
2232 * incoming message to be used in the column info */
2233 con_format = tvb_get_uint8(tvb, offset);
2234 update_id = tvb_get_uint8(tvb, offset + 2);
2235
2236 /* Make entries in Protocol column and Info column on summary display */
2237 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Motion");
2238
2239 /* Add connection format and update number to the info column */
2240 col_add_fstr( pinfo->cinfo, COL_INFO, "%s, Update Id: %d",
2241 val_to_str(pinfo->pool, con_format, cip_con_format_vals, "Unknown connection format (%x)"), update_id );
2242
2243 /* Attempt to classify the incoming header */
2244 if (( con_format == FORMAT_VAR_CONTROL_TO_DEVICE6 ) ||
2245 ( con_format == FORMAT_VAR_DEVICE_TO_CONTROL7 ))
2246 {
2247 /* Sizes of the individual channels within the connection */
2248 uint32_t cyc_size, cyc_blk_size, evnt_size, servc_size;
2249 uint32_t inst_count = 0, inst;
2250 uint32_t format_rev = 0;
2251
2252 /* Dissect the header fields */
2253 switch(con_format)
2254 {
2255 case FORMAT_VAR_CONTROL_TO_DEVICE6:
2256 format_rev = tvb_get_uint8(tvb, offset + 1);
2257 offset = dissect_var_cont_conn_header(tvb, proto_tree_top, &inst_count, offset);
2258 break;
2259 case FORMAT_VAR_DEVICE_TO_CONTROL7:
2260 format_rev = tvb_get_uint8(tvb, offset + 1);
2261 offset = dissect_var_devce_conn_header(tvb, proto_tree_top, &inst_count, offset);
2262 break;
2263 }
2264
2265 if (format_rev != ConnPoint)
2266 {
2267 expert_add_info(pinfo, proto_item_top, &ei_format_rev_conn_pt);
2268 }
2269
2270 /* Repeat the following dissections for each instance within the payload */
2271 for( inst = 0; inst < inst_count; inst++ )
2272 {
2273 /* Actual instance number from header field */
2274 uint8_t instance;
2275
2276 /* Dissect the instance data header */
2277 dissect_var_inst_header( tvb, proto_tree_top, offset, &instance,
2278 &cyc_size, &cyc_blk_size, &evnt_size, &servc_size );
2279
2280 /* Increment the offset to just beyond the instance header */
2281 offset += 8;
2282
2283 /* Dissect the cyclic command (actual) data if any exists */
2284 /* Dissect the cyclic write (read) data if any exists */
2285 /* Dissect the event data block if there is any event data */
2286 switch(con_format)
2287 {
2288 case FORMAT_VAR_CONTROL_TO_DEVICE6:
2289 if ( cyc_size > 0 )
2290 offset = dissect_cntr_cyclic(tvb, proto_tree_top, offset, cyc_size);
2291 if ( cyc_blk_size > 0 )
2292 offset = dissect_cyclic_wt(tvb, proto_tree_top, offset, cyc_blk_size);
2293 if ( evnt_size > 0 )
2294 offset = dissect_cntr_event(tvb, proto_tree_top, offset, evnt_size);
2295 if ( servc_size > 0 )
2296 offset = dissect_cntr_service(tvb, pinfo, proto_tree_top, offset, servc_size, instance);
2297 break;
2298 case FORMAT_VAR_DEVICE_TO_CONTROL7:
2299 if ( cyc_size > 0 )
2300 offset = dissect_device_cyclic(tvb, proto_tree_top, offset, cyc_size);
2301 if ( cyc_blk_size > 0 )
2302 offset = dissect_cyclic_rd( tvb, proto_tree_top, offset, cyc_blk_size );
2303 if ( evnt_size > 0 )
2304 offset = dissect_devce_event(tvb, proto_tree_top, offset, evnt_size);
2305 if ( servc_size > 0 )
2306 offset = dissect_devce_service(tvb, pinfo, proto_tree_top, offset, servc_size, instance);
2307 break;
2308 }
2309
2310 } /* End of instance for( ) loop */
2311 }
2312
2313 // Display any remaining unparsed data.
2314 int remain_len = tvb_reported_length_remaining(tvb, offset);
2315 if (remain_len > 0)
2316 {
2317 proto_tree_add_item(proto_tree_top, hf_cip_data, tvb, offset, remain_len, ENC_NA0x00000000);
2318 }
2319
2320 return tvb_captured_length(tvb);
2321}
2322
2323static int dissect_cipmotion3(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U___attribute__((unused)))
2324{
2325 cip_conn_info_t conn_info;
2326 memset(&conn_info, 0, sizeof(conn_info));
2327 conn_info.connection_path.iConnPoint = 3;
2328
2329 cip_io_data_input io_data_input;
2330 io_data_input.conn_info = &conn_info;
2331
2332 return dissect_cipmotion(tvb, pinfo, tree, &io_data_input);
2333}
2334
2335int dissect_motion_configuration_block(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, proto_item* item, int offset)
2336{
2337 proto_item* config_item;
2338 proto_tree* config_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_configuration_block, &config_item, "Motion Configuration Block");
2339
2340 proto_tree_add_item(config_tree, hf_configuration_block_format_rev, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000);
2341 int parsed_len = 1;
2342
2343 parsed_len += dissect_connection_configuration_bits(pinfo, config_tree, item, tvb, offset + parsed_len, 1);
2344
2345 // 2 reserved bytes
2346 parsed_len += 2;
2347
2348 proto_tree_add_item(config_tree, hf_configuration_block_drive_power_struct_id, tvb, offset + parsed_len, 4, ENC_LITTLE_ENDIAN0x80000000);
2349 parsed_len += 4;
2350
2351 proto_item_set_len(config_item, parsed_len);
2352
2353 return parsed_len;
2354}
2355
2356/*
2357 * Function name: proto_register_cipmotion
2358 *
2359 * Purpose: Register the protocol with Wireshark, a script will add this protocol
2360 * to the list of protocols during the build process. This function is where the
2361 * header fields and subtree identifiers are registered.
2362 *
2363 * Returns: void
2364 */
2365void
2366proto_register_cipmotion(void)
2367{
2368 /* This is a list of header fields that can be used in the dissection or
2369 * to use in a filter expression */
2370 static hf_register_info hf[] =
2371 {
2372 /* Connection format header field, the first byte in the message which
2373 * determines if the message is fixed or variable, controller to device,
2374 * device to controller, etc. */
2375 { &hf_cip_format,
2376 { "Connection Format", "cipm.format",
2377 FT_UINT8, BASE_DEC, VALS(cip_con_format_vals)((0 ? (const struct _value_string*)0 : ((cip_con_format_vals)
)))
, 0,
2378 "Message connection format", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2379 },
2380
2381 /* Connection format revision header field */
2382 { &hf_cip_revision,
2383 { "Format Revision", "cipm.revision",
2384 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2385 "Message format revision", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2386 },
2387
2388 { &hf_cip_class1_seqnum,
2389 { "CIP Class 1 Sequence Count", "cipm.class1seqnum",
2390 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
2391 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2392 },
2393
2394 { &hf_configuration_block_format_rev,
2395 { "Format Revision", "cipm.config.format_rev",
2396 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2397 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2398 },
2399
2400 { &hf_configuration_block_drive_power_struct_id,
2401 { "Drive Power Structure Class ID", "cipm.config.drive_class_id",
2402 FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2403 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2404 },
2405
2406 { &hf_cip_updateid,
2407 { "Update Id", "cipm.updateid",
2408 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2409 "Cyclic Transaction Number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2410 },
2411 { &hf_cip_instance_cnt,
2412 { "Instance Count", "cipm.instancecount",
2413 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2414 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2415 },
2416 { &hf_cip_last_update,
2417 { "Last Update Id", "cipm.lastupdate",
2418 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2419 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2420 },
2421 { &hf_cip_node_status,
2422 { "Node Status", "cipm.nodestatus",
2423 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2424 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2425 },
2426 { &hf_cip_node_control,
2427 { "Node Control", "cipm.nodecontrol",
2428 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2429 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2430 },
2431 { &hf_cip_node_control_remote,
2432 { "Remote Control", "cipm.remote",
2433 FT_BOOLEAN, 8, NULL((void*)0), 0x01,
2434 "Node Control: Remote Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2435 },
2436 { &hf_cip_node_control_sync,
2437 { "Sync Control", "cipm.sync",
2438 FT_BOOLEAN, 8, NULL((void*)0), 0x02,
2439 "Node Control: Synchronous Operation", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2440 },
2441 { &hf_cip_node_data_valid,
2442 { "Data Valid", "cipm.valid",
2443 FT_BOOLEAN, 8, NULL((void*)0), 0x04,
2444 "Node Control: Data Valid", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2445 },
2446 { &hf_cip_node_fault_reset,
2447 { "Node Fault Reset", "cipm.fltrst",
2448 FT_BOOLEAN, 8, NULL((void*)0), 0x08,
2449 "Node Control: Node Fault Reset", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2450 },
2451 { &hf_cip_node_device_faulted,
2452 { "Faulted", "cipm.flt",
2453 FT_BOOLEAN, 8, NULL((void*)0), 0x08,
2454 "Node Control: Device Faulted", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2455 },
2456 { &hf_cip_node_fltalarms,
2457 { "Node Faults and Alarms", "cipm.fltalarms",
2458 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2459 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2460 },
2461 { &hf_cip_time_data_set,
2462 { "Time Data Set", "cipm.timedataset",
2463 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2464 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2465 },
2466 { &hf_cip_time_data_stamp,
2467 { "Time Stamp", "cipm.time.stamp",
2468 FT_BOOLEAN, 8, NULL((void*)0), TIME_DATA_SET_TIME_STAMP0x1,
2469 "Time Data Set: Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2470 },
2471 { &hf_cip_time_data_offset,
2472 { "Time Offset", "cipm.time.offset",
2473 FT_BOOLEAN, 8, NULL((void*)0), TIME_DATA_SET_TIME_OFFSET0x2,
2474 "Time Data Set: Time Offset", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2475 },
2476 { &hf_cip_time_data_diag,
2477 { "Update Diagnostics", "cipm.time.update",
2478 FT_BOOLEAN, 8, NULL((void*)0), TIME_DATA_SET_UPDATE_DIAGNOSTICS0x4,
2479 "Time Data Set: Update Diagnostics", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2480 },
2481 { &hf_cip_time_data_time_diag,
2482 { "Time Diagnostics", "cipm.time.diag",
2483 FT_BOOLEAN, 8, NULL((void*)0), TIME_DATA_SET_TIME_DIAGNOSTICS0x8,
2484 "Time Data Set: Time Diagnostics", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2485 },
2486
2487 { &hf_cip_cont_time_stamp,
2488 { "Controller Time Stamp", "cipm.ctrltimestamp",
2489 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2490 "Time Data Set: Controller Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2491 },
2492 { &hf_cip_cont_time_offset,
2493 { "Controller Time Offset", "cipm.ctrltimeoffser",
2494 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2495 "Time Data Set: Controller Time Offset", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2496 },
2497 { &hf_cip_data_rx_time_stamp,
2498 { "Data Received Time Stamp", "cipm.rxtimestamp",
2499 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2500 "Time Data Set: Data Received Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2501 },
2502 { &hf_cip_data_tx_time_stamp,
2503 { "Data Transmit Time Stamp", "cipm.txtimestamp",
2504 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2505 "Time Data Set: Data Transmit Time Offset", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2506 },
2507 { &hf_cip_devc_time_stamp,
2508 { "Device Time Stamp", "cipm.devctimestamp",
2509 FT_UINT64, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_nanosecond_nanoseconds)((0 ? (const struct unit_name_string*)0 : ((&units_nanosecond_nanoseconds
))))
, 0,
2510 "Time Data Set: Device Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2511 },
2512 { &hf_cip_devc_time_offset,
2513 { "Device Time Offset", "cipm.devctimeoffser",
2514 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2515 "Time Data Set: Device Time Offset", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2516 },
2517 { &hf_cip_lost_update,
2518 { "Lost Updates", "cipm.lostupdates",
2519 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2520 "Time Data Set: Lost Updates", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2521 },
2522 { &hf_cip_late_update,
2523 { "Lost Updates", "cipm.lateupdates",
2524 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2525 "Time Data Set: Late Updates", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2526 },
2527
2528 { &hf_cip_motor_cntrl,
2529 { "Control Mode", "cipm.ctrlmode",
2530 FT_UINT8, BASE_DEC, VALS(cip_motor_control_vals)((0 ? (const struct _value_string*)0 : ((cip_motor_control_vals
))))
, 0,
2531 "Cyclic Data Block: Motor Control Mode", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2532 },
2533
2534 { &hf_cip_feedback,
2535 { "Feedback Information", "cipm.feedback",
2536 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2537 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2538 },
2539 { &hf_cip_feedback_mode,
2540 { "Feedback Mode", "cipm.feedback_mode",
2541 FT_UINT8, BASE_DEC, VALS(cip_feedback_mode_vals)((0 ? (const struct _value_string*)0 : ((cip_feedback_mode_vals
))))
, FEEDBACK_MODE_BITS0x0F,
2542 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2543 },
2544 { &hf_cip_feedback_data_type,
2545 { "Feedback Data Type", "cipm.feedback_data_type",
2546 FT_UINT8, BASE_DEC, VALS(cip_feedback_type_vals)((0 ? (const struct _value_string*)0 : ((cip_feedback_type_vals
))))
, FEEDBACK_DATA_TYPE_BITS0x30,
2547 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2548 },
2549
2550 { &hf_cip_controller_update_delay_high_limit, { "Controller Update Delay High Limit", "cipm.controller_update_delay_high_limit", FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2551 { &hf_cip_controller_update_delay_low_limit, { "Controller Update Delay Low Limit", "cipm.controller_update_delay_low_limit", FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2552 { &hf_cip_sync_threshold, { "Sync Threshold", "cipm.sync_threshold", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_nanosecond_nanoseconds)((0 ? (const struct unit_name_string*)0 : ((&units_nanosecond_nanoseconds
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2553 { &hf_cip_step_threshold, { "Step Threshold", "cipm.step_threshold", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_nanosecond_nanoseconds)((0 ? (const struct unit_name_string*)0 : ((&units_nanosecond_nanoseconds
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2554 { &hf_cip_control_method, { "Control Method", "cipm.control_method", FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2555 { &hf_cip_feedback_unit_ratio, { "Feedback Unit Ratio", "cipm.feedback_unit_ratio", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2556 { &hf_cip_velocity_threshold, { "Velocity Threshold", "cipm.velocity_threshold", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2557 { &hf_cip_velocity_lock_tolerance, { "Velocity Lock Tolerance", "cipm.velocity_lock_tolerance", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2558 { &hf_cip_velocity_standstill_window, { "Velocity Standstill Window", "cipm.velocity_standstill_window", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2559 { &hf_cip_proving_configuration, { "Proving Configuration", "cipm.proving_configuration", FT_UINT32, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2560 { &hf_cip_torque_prove_current, { "Torque Prove Current", "cipm.torque_prove_current", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2561 { &hf_cip_brake_test_torque, { "Brake Test Torque", "cipm.brake_test_torque", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2562 { &hf_cip_zero_speed, { "Zero Speed", "cipm.zero_speed", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2563 { &hf_cip_zero_speed_time, { "Zero Speed Time", "cipm.zero_speed_time", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2564 { &hf_cip_dc_bus_voltage, { "DC Bus Voltage", "cipm.dc_bus_voltage", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2565 { &hf_cip_bus_regulator_action, { "Bus Regulator Action", "cipm.bus_regulator_action", FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2566 { &hf_cip_inverter_capacity, { "Inverter Capacity", "cipm.inverter_capacity", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2567 { &hf_cip_converter_thermal_overload_user_limit, { "Converter Thermal Overload User Limit", "cipm.converter_thermal_overload_user_limit", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2568 { &hf_cip_bus_undervoltage_user_limit, { "Bus Undervoltage User Limit", "cipm.bus_undervoltage_user_limit", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2569 { &hf_cip_rotary_motor_poles, { "Rotary Motor Poles", "cipm.rotary_motor_poles", FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2570 { &hf_cip_rotary_motor_inertia, { "Rotary Motor Inertia", "cipm.rotary_motor_inertia", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2571 { &hf_cip_rotary_motor_max_speed, { "Rotary Motor Max Speed", "cipm.rotary_motor_max_speed", FT_FLOAT, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2572
2573 { &hf_connection_configuration_bits,
2574 { "Connection Configuration Bits", "cipm.ccb",
2575 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2576 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2577 },
2578 { &hf_connection_configuration_bits_power,
2579 { "Verify Power Ratings", "cipm.ccb.verify_power_ratings",
2580 FT_BOOLEAN, 8, NULL((void*)0), 0x01,
2581 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2582 { &hf_connection_configuration_bits_safety_bit_valid,
2583 { "Networked Safety Bit Valid", "cipm.ccb.networked_safety_bit_valid",
2584 FT_BOOLEAN, 8, NULL((void*)0), 0x02,
2585 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2586 { &hf_connection_configuration_bits_allow_network_safety,
2587 { "Allow Networked Safety", "cipm.ccb.allow_networked_safety",
2588 FT_BOOLEAN, 8, NULL((void*)0), 0x04,
2589 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2590
2591 { &hf_cip_axis_control,
2592 { "Axis Control", "cipm.axisctrl",
2593 FT_UINT8, BASE_DEC, VALS(cip_axis_control_vals)((0 ? (const struct _value_string*)0 : ((cip_axis_control_vals
))))
, 0,
2594 "Cyclic Data Block: Axis Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2595 },
2596 { &hf_cip_control_status,
2597 { "Control Status", "cipm.csts",
2598 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2599 "Cyclic Data Block: Axis Control Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2600 },
2601 { &hf_cip_control_status_complete,
2602 { "Configuration Complete", "cipm.control_status.complete",
2603 FT_BOOLEAN, 8, NULL((void*)0), 0x01,
2604 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2605 { &hf_cip_control_status_bus_up,
2606 { "Converter Bus Up", "cipm.control_status.bus_up",
2607 FT_BOOLEAN, 8, NULL((void*)0), 0x04,
2608 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2609 { &hf_cip_control_status_bus_unload,
2610 { "Converter Bus Unload", "cipm.control_status.bus_unload",
2611 FT_BOOLEAN, 8, NULL((void*)0), 0x08,
2612 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2613 { &hf_cip_control_status_power_loss,
2614 { "Converter AC Power Loss", "cipm.control_status.power_loss",
2615 FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2616 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2617 { &hf_cip_axis_response,
2618 { "Axis Response", "cipm.axisresp",
2619 FT_UINT8, BASE_DEC, VALS(cip_axis_response_vals)((0 ? (const struct _value_string*)0 : ((cip_axis_response_vals
))))
, 0,
2620 "Cyclic Data Block: Axis Response", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2621 },
2622 { &hf_cip_axis_resp_stat,
2623 { "Response Status", "cipm.respstat",
2624 FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
2625 "Cyclic Data Block: Axis Response Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2626 },
2627 { &hf_cip_group_sync,
2628 { "Group Sync Status", "cipm.syncstatus",
2629 FT_UINT8, BASE_HEX, VALS(cip_sync_status_vals)((0 ? (const struct _value_string*)0 : ((cip_sync_status_vals
))))
, 0,
2630 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2631 },
2632 { &hf_cip_cmd_data_set,
2633 { "Command Data Set", "cipm.cmdset",
2634 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2635 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2636 },
2637 { &hf_cip_act_data_set,
2638 { "Actual Data Set", "cipm.actset",
2639 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2640 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2641 },
2642 { &hf_cip_sts_data_set,
2643 { "Status Data Set", "cipm.stsset",
2644 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2645 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2646 },
2647
2648 // Command Data Set
2649 { &hf_cip_cmd_data_pos_cmd,
2650 { "Command Position", "cipm.cmd.pos",
2651 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_POSITION0x01,
2652 "Command Data Set: Command Position", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2653 },
2654 { &hf_cip_cmd_data_vel_cmd,
2655 { "Command Velocity", "cipm.cmd.vel",
2656 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_VELOCITY0x02,
2657 "Command Data Set: Command Velocity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2658 },
2659 { &hf_cip_cmd_data_acc_cmd,
2660 { "Command Acceleration", "cipm.cmd.acc",
2661 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_ACCELERATION0x04,
2662 "Command Data Set: Command Acceleration", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2663 },
2664 { &hf_cip_cmd_data_trq_cmd,
2665 { "Command Torque", "cipm.cmd.trq",
2666 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_TORQUE0x08,
2667 "Command Data Set: Command Torque", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2668 },
2669 { &hf_cip_cmd_data_unwind_cycle_count,
2670 { "Unwind Cycle Count", "cipm.cmd.unwind",
2671 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_UNWIND_CYCLE_COUNT0x40,
2672 "Command Data Set: Unwind Cycle Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2673 },
2674 { &hf_cip_cmd_data_pos_displacement,
2675 { "Position Displacement", "cipm.cmd.pos_displacement",
2676 FT_BOOLEAN, 8, NULL((void*)0), COMMAND_DATA_SET_POSITION_DISPLACE0x80,
2677 "Command Data Set: Position Displacement", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2678 },
2679
2680 // Actual Data Set
2681 { &hf_cip_act_data_pos,
2682 { "Actual Position", "cipm.act.pos",
2683 FT_BOOLEAN, 8, NULL((void*)0), ACTUAL_DATA_SET_POSITION0x01,
2684 "Actual Data Set: Actual Position", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2685 },
2686 { &hf_cip_act_data_vel,
2687 { "Actual Velocity", "cipm.act.vel",
2688 FT_BOOLEAN, 8, NULL((void*)0), ACTUAL_DATA_SET_VELOCITY0x02,
2689 "Actual Data Set: Actual Velocity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2690 },
2691 { &hf_cip_act_data_acc,
2692 { "Actual Acceleration", "cipm.act.acc",
2693 FT_BOOLEAN, 8, NULL((void*)0), ACTUAL_DATA_SET_ACCELERATION0x04,
2694 "Actual Data Set: Actual Acceleration", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2695 },
2696 { &hf_cip_act_unwind_cycle_count,
2697 { "Unwind Cycle Count", "cipm.act.unwind",
2698 FT_BOOLEAN, 8, NULL((void*)0), ACTUAL_DATA_SET_UNWIND_CYCLE_COUNT0x40,
2699 "Actual Data Set: Unwind Cycle Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2700 },
2701 { &hf_cip_act_pos_displacement,
2702 { "Position Displacement", "cipm.act.pos_displacement",
2703 FT_BOOLEAN, 8, NULL((void*)0), ACTUAL_DATA_SET_POSITION_DISPLACE0x80,
2704 "Actual Data Set: Position Displacement", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2705 },
2706
2707 { &hf_cip_axis_fault,
2708 { "Axis Fault Code", "cipm.fault.code",
2709 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2710 "Status Data Set: Fault Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2711 },
2712 { &hf_cip_fault_type,
2713 { "Axis Fault Type", "cipm.flttype",
2714 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2715 "Axis Status: Axis Fault Type", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2716 },
2717 { &hf_cip_fault_sub_code,
2718 { "Axis Fault Sub Code", "cipm.fltsubcode",
2719 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2720 "Axis Status: Axis Fault Sub Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2721 },
2722 { &hf_cip_fault_action,
2723 { "Axis Fault Action", "cipm.fltaction",
2724 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2725 "Axis Status: Axis Fault Action", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2726 },
2727 { &hf_cip_fault_time_stamp,
2728 { "Axis Fault Time Stamp", "cipm.flttimestamp",
2729 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2730 "Axis Status: Axis Fault Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2731 },
2732 { &hf_cip_alarm_type,
2733 { "Axis Fault Type", "cipm.alarmtype",
2734 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2735 "Axis Status: Axis Alarm Type", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2736 },
2737 { &hf_cip_alarm_sub_code,
2738 { "Axis Alarm Sub Code", "cipm.alarmsubcode",
2739 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2740 "Axis Status: Axis Alarm Sub Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2741 },
2742 { &hf_cip_alarm_state,
2743 { "Axis Alarm State", "cipm.alarmstate",
2744 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2745 "Axis Status: Axis Alarm State", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2746 },
2747 { &hf_cip_alarm_time_stamp,
2748 { "Axis Fault Time Stamp", "cipm.alarmtimestamp",
2749 FT_UINT64, BASE_DEC, NULL((void*)0), 0,
2750 "Axis Status: Axis Alarm Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2751 },
2752 { &hf_cip_axis_status,
2753 { "Axis Status", "cipm.axisstatus",
2754 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2755 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2756 },
2757 { &hf_cip_axis_status_mfg,
2758 { "Axis Status Mfg", "cipm.axisstatusmfg",
2759 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2760 "Axis Status, Manufacturer Specific", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2761 },
2762 { &hf_cip_axis_io_status,
2763 { "Axis I/O Status", "cipm.axisiostatus",
2764 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2765 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2766 },
2767 { &hf_cip_axis_io_status_mfg,
2768 { "Axis I/O Status Mfg", "cipm.axisiostatusmfg",
2769 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2770 "Axis I/O Status, Manufacturer Specific", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2771 },
2772 { &hf_cip_axis_safety_status,
2773 { "Axis Safety Status", "cipm.safetystatus",
2774 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2775 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2776 },
2777 { &hf_cip_axis_safety_status_mfg,
2778 { "Axis Safety Status Mfg", "cipm.safetystatusmfg",
2779 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2780 "Axis Safety Status, Manufacturer Specific", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2781 },
2782 { &hf_cip_axis_safety_state,
2783 { "Axis Safety State", "cipm.safetystate",
2784 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
2785 "Axis Safety Sate", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2786 },
2787 { &hf_cip_sts_flt,
2788 { "Axis Fault Codes", "cipm.sts.flt",
2789 FT_BOOLEAN, 8, NULL((void*)0), STATUS_DATA_SET_AXIS_FAULT0x01,
2790 "Status Data Set: Axis Fault Codes", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2791 },
2792 { &hf_cip_sts_alrm,
2793 { "Axis Alarm Codes", "cipm.sts.alarm",
2794 FT_BOOLEAN, 8, NULL((void*)0), STATUS_DATA_SET_AXIS_ALARM0x02,
2795 "Status Data Set: Axis Alarm Codes", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2796 },
2797 { &hf_cip_sts_sts,
2798 { "Axis Status", "cipm.sts.sts",
2799 FT_BOOLEAN, 8, NULL((void*)0), STATUS_DATA_SET_AXIS_STATUS0x04,
2800 "Status Data Set: Axis Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2801 },
2802 { &hf_cip_sts_iosts,
2803 { "Axis I/O Status", "cipm.sts.iosts",
2804 FT_BOOLEAN, 8, NULL((void*)0), STATUS_DATA_SET_AXIS_IO_STATUS0x08,
2805 "Status Data Set: Axis I/O Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2806 },
2807 { &hf_cip_sts_axis_safety,
2808 { "Axis Safety Status", "cipm.sts.safety",
2809 FT_BOOLEAN, 8, NULL((void*)0), STATUS_DATA_SET_AXIS_SAFETY0x10,
2810 "Status Data Set: Axis Safety Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2811 },
2812 { &hf_cip_intrp,
2813 { "Command Target Update", "cipm.intrp",
2814 FT_UINT8, BASE_DEC, VALS(cip_interpolation_vals)((0 ? (const struct _value_string*)0 : ((cip_interpolation_vals
))))
, COMMAND_CONTROL_TARGET_UPDATE0x03,
2815 "Cyclic Data Block: Command Target Update", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2816 },
2817 { &hf_cip_position_data_type,
2818 { "Command Position Data Type", "cipm.posdatatype",
2819 FT_UINT8, BASE_DEC, VALS(cip_pos_data_type_vals)((0 ? (const struct _value_string*)0 : ((cip_pos_data_type_vals
))))
, COMMAND_CONTROL_POSITION_DATA_TYPE0x0C,
2820 "Cyclic Data Block: Command Position Data Type", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2821 },
2822 { &hf_cip_axis_state,
2823 { "Axis State", "cipm.axste",
2824 FT_UINT8, BASE_DEC, VALS(cip_axis_state_vals)((0 ? (const struct _value_string*)0 : ((cip_axis_state_vals)
)))
, 0,
2825 "Cyclic Data Block: Axis State", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2826 },
2827 { &hf_cip_command_control,
2828 { "Command Control", "cipm.cmdcontrol",
2829 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2830 "Cyclic Data Block: Command Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2831 },
2832 { &hf_cip_cyclic_wrt_data,
2833 { "Write Data", "cipm.writedata",
2834 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
2835 "Cyclic Write: Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2836 },
2837 { &hf_cip_cyclic_rd_data,
2838 { "Read Data", "cipm.readdata",
2839 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
2840 "Cyclic Read: Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2841 },
2842 { &hf_cip_cyclic_write_blk,
2843 { "Write Block", "cipm.writeblk",
2844 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2845 "Cyclic Data Block: Write Block Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2846 },
2847 { &hf_cip_cyclic_read_blk,
2848 { "Read Block", "cipm.readblk",
2849 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2850 "Cyclic Data Block: Read Block Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2851 },
2852 { &hf_cip_cyclic_write_sts,
2853 { "Write Status", "cipm.writests",
2854 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2855 "Cyclic Data Block: Write Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2856 },
2857 { &hf_cip_cyclic_read_sts,
2858 { "Read Status", "cipm.readsts",
2859 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2860 "Cyclic Data Block: Read Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2861 },
2862 { &hf_cip_event_checking,
2863 { "Event Checking Control", "cipm.evntchkcontrol",
2864 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2865 "Event Channel: Event Checking Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2866 },
2867 { &hf_cip_event_ack,
2868 { "Event Acknowledgement", "cipm.evntack",
2869 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2870 "Event Channel: Event Acknowledgement", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2871 },
2872 { &hf_cip_event_status,
2873 { "Event Checking Status", "cipm.evntchkstatus",
2874 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
2875 "Event Channel: Event Checking Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2876 },
2877 { &hf_cip_event_id,
2878 { "Event Id", "cipm.evntid",
2879 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2880 "Event Channel: Event Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2881 },
2882 { &hf_cip_event_pos,
2883 { "Event Position", "cipm.evntpos",
2884 FT_INT32, BASE_DEC, NULL((void*)0), 0,
2885 "Event Channel: Event Position", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2886 },
2887 { &hf_cip_event_ts,
2888 { "Event Time Stamp", "cipm.evntimestamp",
2889 FT_UINT64, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_nanosecond_nanoseconds)((0 ? (const struct unit_name_string*)0 : ((&units_nanosecond_nanoseconds
))))
, 0,
2890 "Event Channel: Time Stamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2891 },
2892
2893 { &hf_cip_evnt_ctrl_reg1_pos,
2894 { "Reg 1 Pos Edge", "cipm.evnt.ctrl.reg1posedge",
2895 FT_BOOLEAN, 32, NULL((void*)0), 0x00000001,
2896 "Event Checking Control: Reg 1 Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2897 },
2898 { &hf_cip_evnt_ctrl_reg1_neg,
2899 { "Reg 1 Neg Edge", "cipm.evnt.ctrl.reg1negedge",
2900 FT_BOOLEAN, 32, NULL((void*)0), 0x00000002,
2901 "Event Checking Control: Reg 1 Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2902 },
2903 { &hf_cip_evnt_ctrl_reg2_pos,
2904 { "Reg 2 Pos Edge", "cipm.evnt.ctrl.reg2posedge",
2905 FT_BOOLEAN, 32, NULL((void*)0), 0x00000004,
2906 "Event Checking Control: Reg 2 Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2907 },
2908 { &hf_cip_evnt_ctrl_reg2_neg,
2909 { "Reg 2 Neg Edge", "cipm.evnt.ctrl.reg2negedge",
2910 FT_BOOLEAN, 32, NULL((void*)0), 0x00000008,
2911 "Event Checking Control: Reg 2 Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2912 },
2913 { &hf_cip_evnt_ctrl_reg1_posrearm,
2914 { "Reg 1 Pos Rearm", "cipm.evnt.ctrl.reg1posrearm",
2915 FT_BOOLEAN, 32, NULL((void*)0), 0x00000100,
2916 "Event Checking Control: Reg 1 Pos Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2917 },
2918 { &hf_cip_evnt_ctrl_reg1_negrearm,
2919 { "Reg 1 Neg Rearm", "cipm.evnt.ctrl.reg1negrearm",
2920 FT_BOOLEAN, 32, NULL((void*)0), 0x00000200,
2921 "Event Checking Control: Reg 1 Neg Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2922 },
2923 { &hf_cip_evnt_ctrl_reg2_posrearm,
2924 { "Reg 2 Pos Rearm", "cipm.evnt.ctrl.reg2posrearm",
2925 FT_BOOLEAN, 32, NULL((void*)0), 0x00000400,
2926 "Event Checking Control: Reg 2 Pos Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2927 },
2928 { &hf_cip_evnt_ctrl_reg2_negrearm,
2929 { "Reg 2 Neg Rearm", "cipm.evnt.ctrl.reg2negrearm",
2930 FT_BOOLEAN, 32, NULL((void*)0), 0x00000800,
2931 "Event Checking Control: Reg 2 Neg Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2932 },
2933 { &hf_cip_evnt_ctrl_marker_pos,
2934 { "Marker Pos Edge", "cipm.evnt.ctrl.mrkrpos",
2935 FT_BOOLEAN, 32, NULL((void*)0), 0x00010000,
2936 "Event Checking Control: Marker Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2937 },
2938 { &hf_cip_evnt_ctrl_marker_neg,
2939 { "Marker Neg Edge", "cipm.evnt.ctrl.mrkrneg",
2940 FT_BOOLEAN, 32, NULL((void*)0), 0x00020000,
2941 "Event Checking Control: Marker Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2942 },
2943 { &hf_cip_evnt_ctrl_home_pos,
2944 { "Home Pos Edge", "cipm.evnt.ctrl.homepos",
2945 FT_BOOLEAN, 32, NULL((void*)0), 0x00040000,
2946 "Event Checking Control: Home Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2947 },
2948 { &hf_cip_evnt_ctrl_home_neg,
2949 { "Home Neg Edge", "cipm.evnt.ctrl.homeneg",
2950 FT_BOOLEAN, 32, NULL((void*)0), 0x00080000,
2951 "Event Checking Control: Home Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2952 },
2953 { &hf_cip_evnt_ctrl_home_pp,
2954 { "Home-Switch-Marker Plus Plus", "cipm.evnt.ctrl.homepp",
2955 FT_BOOLEAN, 32, NULL((void*)0), 0x00100000,
2956 "Event Checking Control: Home-Switch-Marker Plus Plus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2957 },
2958 { &hf_cip_evnt_ctrl_home_pm,
2959 { "Home-Switch-Marker Plus Minus", "cipm.evnt.ctrl.homepm",
2960 FT_BOOLEAN, 32, NULL((void*)0), 0x00200000,
2961 "Event Checking Control: Home-Switch-Marker Plus Minus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2962 },
2963 { &hf_cip_evnt_ctrl_home_mp,
2964 { "Home-Switch-Marker Minus Plus", "cipm.evnt.ctrl.homemp",
2965 FT_BOOLEAN, 32, NULL((void*)0), 0x00400000,
2966 "Event Checking Control: Home-Switch-Marker Minus Plus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2967 },
2968 { &hf_cip_evnt_ctrl_home_mm,
2969 { "Home-Switch-Marker Minus Minus", "cipm.evnt.ctrl.homemm",
2970 FT_BOOLEAN, 32, NULL((void*)0), 0x00800000,
2971 "Event Checking Control: Home-Switch-Marker Minus Minus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2972 },
2973 { &hf_cip_evnt_ctrl_acks,
2974 { "Event Block Count", "cipm.evnt.ctrl.acks",
2975 FT_UINT32, BASE_DEC, NULL((void*)0), 0x70000000,
2976 "Event Checking Control: Event Block Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2977 },
2978 { &hf_cip_evnt_extend_format,
2979 { "Extended Event Format", "cipm.evnt.extend",
2980 FT_BOOLEAN, 32, NULL((void*)0), 0x80000000,
2981 "Event Checking Control: Extended Event Format", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2982 },
2983
2984 { &hf_cip_evnt_sts_reg1_pos,
2985 { "Reg 1 Pos Edge", "cipm.evnt.sts.reg1posedge",
2986 FT_BOOLEAN, 32, NULL((void*)0), 0x00000001,
2987 "Event Checking Status: Reg 1 Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2988 },
2989 { &hf_cip_evnt_sts_reg1_neg,
2990 { "Reg 1 Neg Edge", "cipm.evnt.sts.reg1negedge",
2991 FT_BOOLEAN, 32, NULL((void*)0), 0x00000002,
2992 "Event Checking Status: Reg 1 Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2993 },
2994 { &hf_cip_evnt_sts_reg2_pos,
2995 { "Reg 2 Pos Edge", "cipm.evnt.sts.reg2posedge",
2996 FT_BOOLEAN, 32, NULL((void*)0), 0x00000004,
2997 "Event Checking Status: Reg 2 Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
2998 },
2999 { &hf_cip_evnt_sts_reg2_neg,
3000 { "Reg 2 Neg Edge", "cipm.evnt.sts.reg2negedge",
3001 FT_BOOLEAN, 32, NULL((void*)0), 0x00000008,
3002 "Event Checking Status: Reg 2 Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3003 },
3004 { &hf_cip_evnt_sts_reg1_posrearm,
3005 { "Reg 1 Pos Rearm", "cipm.evnt.sts.reg1posrearm",
3006 FT_BOOLEAN, 32, NULL((void*)0), 0x00000100,
3007 "Event Checking Status: Reg 1 Pos Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3008 },
3009 { &hf_cip_evnt_sts_reg1_negrearm,
3010 { "Reg 1 Neg Rearm", "cipm.evnt.sts.reg1negrearm",
3011 FT_BOOLEAN, 32, NULL((void*)0), 0x00000200,
3012 "Event Checking Status: Reg 1 Neg Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3013 },
3014 { &hf_cip_evnt_sts_reg2_posrearm,
3015 { "Reg 2 Pos Rearm", "cipm.evnt.sts.reg2posrearm",
3016 FT_BOOLEAN, 32, NULL((void*)0), 0x00000400,
3017 "Event Checking Status: Reg 2 Pos Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3018 },
3019 { &hf_cip_evnt_sts_reg2_negrearm,
3020 { "Reg 2 Neg Rearm", "cipm.evnt.sts.reg2negrearm",
3021 FT_BOOLEAN, 32, NULL((void*)0), 0x00000800,
3022 "Event Checking Status: Reg 2 Neg Rearm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3023 },
3024 { &hf_cip_evnt_sts_marker_pos,
3025 { "Marker Pos Edge", "cipm.evnt.sts.mrkrpos",
3026 FT_BOOLEAN, 32, NULL((void*)0), 0x00010000,
3027 "Event Checking Status: Marker Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3028 },
3029 { &hf_cip_evnt_sts_marker_neg,
3030 { "Marker Neg Edge", "cipm.evnt.sts.mrkrneg",
3031 FT_BOOLEAN, 32, NULL((void*)0), 0x00020000,
3032 "Event Checking Status: Marker Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3033 },
3034 { &hf_cip_evnt_sts_home_pos,
3035 { "Home Pos Edge", "cipm.evnt.sts.homepos",
3036 FT_BOOLEAN, 32, NULL((void*)0), 0x00040000,
3037 "Event Checking Status: Home Pos Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3038 },
3039 { &hf_cip_evnt_sts_home_neg,
3040 { "Home Neg Edge", "cipm.evnt.sts.homeneg",
3041 FT_BOOLEAN, 32, NULL((void*)0), 0x00080000,
3042 "Event Checking Status: Home Neg Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3043 },
3044 { &hf_cip_evnt_sts_home_pp,
3045 { "Home-Switch-Marker Plus Plus", "cipm.evnt.sts.homepp",
3046 FT_BOOLEAN, 32, NULL((void*)0), 0x00100000,
3047 "Event Checking Status: Home-Switch-Marker Plus Plus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3048 },
3049 { &hf_cip_evnt_sts_home_pm,
3050 { "Home-Switch-Marker Plus Minus", "cipm.evnt.sts.homepm",
3051 FT_BOOLEAN, 32, NULL((void*)0), 0x00200000,
3052 "Event Checking Status: Home-Switch-Marker Plus Minus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3053 },
3054 { &hf_cip_evnt_sts_home_mp,
3055 { "Home-Switch-Marker Minus Plus", "cipm.evnt.sts.homemp",
3056 FT_BOOLEAN, 32, NULL((void*)0), 0x00400000,
3057 "Event Checking Status: Home-Switch-Marker Minus Plus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3058 },
3059 { &hf_cip_evnt_sts_home_mm,
3060 { "Home-Switch-Marker Minus Minus", "cipm.evnt.sts.homemm",
3061 FT_BOOLEAN, 32, NULL((void*)0), 0x00800000,
3062 "Event Checking Status: Home-Switch-Marker Minus Minus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3063 },
3064 { &hf_cip_evnt_sts_nfs,
3065 { "Event Block Count", "cipm.evnt.sts.nfs",
3066 FT_UINT32, BASE_DEC, NULL((void*)0), 0x70000000,
3067 "Event Checking Status: Event Block Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3068 },
3069
3070 { &hf_cip_evnt_sts_stat,
3071 { "Event Status", "cipm.evnt.stat",
3072 FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
3073 "Event Data Block: Event Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3074 },
3075 { &hf_cip_evnt_type,
3076 { "Event Type", "cipm.evnt.type",
3077 FT_UINT8, BASE_DEC, VALS(cip_event_type_vals)((0 ? (const struct _value_string*)0 : ((cip_event_type_vals)
)))
, 0,
3078 "Event Data Block: Event Type", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3079 },
3080 { &hf_cip_svc_code,
3081 { "Service Code", "cipm.svc.code",
3082 FT_UINT8, BASE_HEX, VALS(cip_sc_vals)((0 ? (const struct _value_string*)0 : ((cip_sc_vals)))), 0,
3083 "Service Data Block: Service Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3084 },
3085 { &hf_cip_svc_sts,
3086 { "General Status", "cipm.svc.sts",
3087 FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
3088 "Service Data Block: General Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3089 },
3090 { &hf_cip_svc_transction,
3091 { "Transaction Id", "cipm.svc.tranid",
3092 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3093 "Service Data Block: Transaction Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3094 },
3095 { &hf_cip_svc_ext_status,
3096 { "Extended Status", "cipm.svc.extstatus",
3097 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3098 "Service Data Block: Extended Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3099 },
3100 { &hf_cip_svc_data,
3101 { "Service Data", "cipm.svc.data",
3102 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
3103 "Service Data Block: Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3104 },
3105 { &hf_cip_attribute_data,
3106 { "Attribute Data", "cipm.attrdata",
3107 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
3108 "Attribute Service: Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3109 },
3110 { &hf_cip_ptp_grandmaster,
3111 { "Grandmaster", "cipm.grandmaster",
3112 FT_UINT64, BASE_HEX, NULL((void*)0), 0,
3113 "Group Sync: Grandmaster Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3114 },
3115
3116 { &hf_cip_svc_get_axis_attr_sts,
3117 { "Attribute Status", "cipm.getaxisattr.sts",
3118 FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
3119 "Service Channel: Get Axis Attribute List Response Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3120 },
3121 { &hf_get_axis_attr_list_attribute_cnt,
3122 { "Number of attributes", "cipm.getaxisattr.cnt",
3123 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3124 "Service Channel: Get Axis Attribute List Attribute Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3125 },
3126 { &hf_get_axis_attr_list_attribute_id,
3127 { "Attribute ID", "cipm.getaxisattr.id",
3128 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3129 "Service Channel: Get Axis Attribute List Attribute ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3130 },
3131 { &hf_get_axis_attr_list_dimension,
3132 { "Dimension", "cipm.getaxisattr.dimension",
3133 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3134 "Service Channel: Get Axis Attribute List Dimension", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3135 },
3136 { &hf_get_axis_attr_list_element_size,
3137 { "Element size", "cipm.getaxisattr.element_size",
3138 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3139 "Service Channel: Get Axis Attribute List Element Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3140 },
3141 { &hf_get_axis_attr_list_start_index,
3142 { "Start index", "cipm.getaxisattr.start_index",
3143 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3144 "Service Channel: Get Axis Attribute List Start index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3145 },
3146 { &hf_get_axis_attr_list_data_elements,
3147 { "Data elements", "cipm.getaxisattr.data_elements",
3148 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3149 "Service Channel: Get Axis Attribute List Data elements", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3150 },
3151
3152 { &hf_cip_svc_set_axis_attr_sts,
3153 { "Attribute Status", "cipm.setaxisattr.sts",
3154 FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
3155 "Service Channel: Set Axis Attribute List Response Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3156 },
3157 { &hf_set_axis_attr_list_attribute_cnt,
3158 { "Number of attributes", "cipm.setaxisattr.cnt",
3159 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3160 "Service Channel: Set Axis Attribute List Attribute Count", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3161 },
3162 { &hf_set_axis_attr_list_attribute_id,
3163 { "Attribute ID", "cipm.setaxisattr.id",
3164 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3165 "Service Channel: Set Axis Attribute List Attribute ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3166 },
3167 { &hf_set_axis_attr_list_dimension,
3168 { "Dimension", "cipm.setaxisattr.dimension",
3169 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3170 "Service Channel: Set Axis Attribute List Dimension", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3171 },
3172 { &hf_set_axis_attr_list_element_size,
3173 { "Element size", "cipm.setaxisattr.element_size",
3174 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3175 "Service Channel: Set Axis Attribute List Element Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3176 },
3177 { &hf_set_axis_attr_list_start_index,
3178 { "Start index", "cipm.setaxisattr.start_index",
3179 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3180 "Service Channel: Set Axis Attribute List Start index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3181 },
3182 { &hf_set_axis_attr_list_data_elements,
3183 { "Data elements", "cipm.setaxisattr.data_elements",
3184 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3185 "Service Channel: Set Axis Attribute List Data elements", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3186 },
3187
3188 { &hf_set_cyclic_list_attribute_cnt,
3189 { "Number of attributes", "cipm.set_cyclic.cnt",
3190 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3191 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3192 },
3193 { &hf_set_cyclic_list_attribute_id,
3194 { "Attribute ID", "cipm.set_cyclic.id",
3195 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3196 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3197 },
3198 { &hf_set_cyclic_list_read_block_id,
3199 { "Cyclic Read Block ID", "cipm.set_cyclic.read_block_id",
3200 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
3201 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3202 },
3203 { &hf_set_cyclic_list_attr_sts,
3204 { "Attribute Status", "cipm.set_cyclic.sts",
3205 FT_UINT8, BASE_DEC | BASE_EXT_STRING0x00000200, &cip_gs_vals_ext, 0,
3206 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3207 },
3208
3209 { &hf_var_devce_instance,
3210 { "Instance Number", "cipm.var_devce.header.instance",
3211 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3212 "Variable Device Header: Instance Number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3213 },
3214 { &hf_var_devce_instance_block_size,
3215 { "Instance Block Size", "cipm.var_devce.header.instance_block_size",
3216 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3217 "Variable Device Header: Instance Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3218 },
3219 { &hf_var_devce_cyclic_block_size,
3220 { "Cyclic Block Size", "cipm.var_devce.header.cyclic_block_size",
3221 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3222 "Variable Device Header: Cyclic Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3223 },
3224 { &hf_var_devce_cyclic_data_block_size,
3225 { "Cyclic Data Block Size", "cipm.var_devce.header.cyclic_data_block_size",
3226 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3227 "Variable Device Header: Cyclic Data Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3228 },
3229 { &hf_var_devce_cyclic_rw_block_size,
3230 { "Cyclic Read/Write Block Size", "cipm.var_devce.header.cyclic_rw_block_size",
3231 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3232 "Variable Device Header: Cyclic Read/Write Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3233 },
3234 { &hf_var_devce_event_block_size,
3235 { "Event Block Size", "cipm.var_devce.header.event_block_size",
3236 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3237 "Variable Device Header: Event Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3238 },
3239 { &hf_var_devce_service_block_size,
3240 { "Service Block Size", "cipm.var_devce.header.service_block_size",
3241 FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_word_words)((0 ? (const struct unit_name_string*)0 : ((&units_word_words
))))
, 0,
3242 "Variable Device Header: Service Block Size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}
3243 },
3244
3245 { &hf_cip_axis_alarm,
3246 { "Axis Alarm Code", "cipm.alarm.code",
3247 FT_UINT8, BASE_DEC, NULL((void*)0), 0,
3248 "Status Data Set: Alarm Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3249 },
3250 { &hf_cip_axis_sts_local_ctrl,
3251 { "Local Control", "cipm.axis.local",
3252 FT_BOOLEAN, 32, NULL((void*)0), 0x00000001,
3253 "Axis Status Data Set: Local Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3254 },
3255 { &hf_cip_axis_sts_alarm,
3256 { "Alarm", "cipm.axis.alarm",
3257 FT_BOOLEAN, 32, NULL((void*)0), 0x00000002,
3258 "Axis Status Data Set: Alarm", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3259 },
3260 { &hf_cip_axis_sts_dc_bus,
3261 { "DC Bus", "cipm.axis.bus",
3262 FT_BOOLEAN, 32, NULL((void*)0), 0x00000004,
3263 "Axis Status Data Set: DC Bus", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3264 },
3265 { &hf_cip_axis_sts_pwr_struct,
3266 { "Power Struct", "cipm.axis.pwr",
3267 FT_BOOLEAN, 32, NULL((void*)0), 0x00000008,
3268 "Axis Status Data Set: Power Struct", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3269 },
3270 { &hf_cip_axis_sts_flux_up,
3271 { "Motor Flux Up", "cipm.axis.flx",
3272 FT_BOOLEAN, 32, NULL((void*)0), 0x00000010,
3273 "Axis Status Data Set: Motor Flux Up", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3274 },
3275 { &hf_cip_axis_sts_tracking,
3276 { "Tracking", "cipm.axis.track",
3277 FT_BOOLEAN, 32, NULL((void*)0), 0x00000020,
3278 "Axis Status Data Set: Tracking", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3279 },
3280 { &hf_cip_axis_sts_pos_lock,
3281 { "Pos Lock", "cipm.axis.poslock",
3282 FT_BOOLEAN, 32, NULL((void*)0), 0x00000040,
3283 "Axis Status Data Set: Pos Lock", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3284 },
3285 { &hf_cip_axis_sts_vel_lock,
3286 { "Vel Lock", "cipm.axis.vellock",
3287 FT_BOOLEAN, 32, NULL((void*)0), 0x00000080,
3288 "Axis Status Data Set: Vel Lock", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3289 },
3290 { &hf_cip_axis_sts_vel_standstill,
3291 { "Vel Standstill", "cipm.axis.nomo",
3292 FT_BOOLEAN, 32, NULL((void*)0), 0x00000100,
3293 "Axis Status Data Set: Vel Standstill", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3294 },
3295 { &hf_cip_axis_sts_vel_threshold,
3296 { "Vel Threshold", "cipm.axis.vthresh",
3297 FT_BOOLEAN, 32, NULL((void*)0), 0x00000200,
3298 "Axis Status Data Set: Vel Threshold", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3299 },
3300 { &hf_cip_axis_sts_vel_limit,
3301 { "Vel Limit", "cipm.axis.vlim",
3302 FT_BOOLEAN, 32, NULL((void*)0), 0x00000400,
3303 "Axis Status Data Set: Vel Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3304 },
3305 { &hf_cip_axis_sts_acc_limit,
3306 { "Acc Limit", "cipm.axis.alim",
3307 FT_BOOLEAN, 32, NULL((void*)0), 0x00000800,
3308 "Axis Status Data Set: Acc Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3309 },
3310 { &hf_cip_axis_sts_dec_limit,
3311 { "Decel Limit", "cipm.axis.dlim",
3312 FT_BOOLEAN, 32, NULL((void*)0), 0x00001000,
3313 "Axis Status Data Set: Decel Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3314 },
3315 { &hf_cip_axis_sts_torque_threshold,
3316 { "Torque Threshold", "cipm.axis.tthresh",
3317 FT_BOOLEAN, 32, NULL((void*)0), 0x00002000,
3318 "Axis Status Data Set: Torque Threshold", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3319 },
3320 { &hf_cip_axis_sts_torque_limit,
3321 { "Torque Limit", "cipm.axis.tlim",
3322 FT_BOOLEAN, 32, NULL((void*)0), 0x00004000,
3323 "Axis Status Data Set: Torque Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3324 },
3325 { &hf_cip_axis_sts_cur_limit,
3326 { "Current Limit", "cipm.axis.ilim",
3327 FT_BOOLEAN, 32, NULL((void*)0), 0x00008000,
3328 "Axis Status Data Set: Current Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3329 },
3330 { &hf_cip_axis_sts_therm_limit,
3331 { "Thermal Limit", "cipm.axis.hot",
3332 FT_BOOLEAN, 32, NULL((void*)0), 0x00010000,
3333 "Axis Status Data Set: Thermal Limit", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3334 },
3335 { &hf_cip_axis_sts_feedback_integ,
3336 { "Feedback Integrity", "cipm.axis.fgood",
3337 FT_BOOLEAN, 32, NULL((void*)0), 0x00020000,
3338 "Axis Status Data Set: Feedback Integrity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3339 },
3340 { &hf_cip_axis_sts_shutdown,
3341 { "Shutdown", "cipm.axis.sdwn",
3342 FT_BOOLEAN, 32, NULL((void*)0), 0x00040000,
3343 "Axis Status Data Set: Shutdown", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3344 },
3345 { &hf_cip_axis_sts_in_process,
3346 { "In Process", "cipm.axis.inp",
3347 FT_BOOLEAN, 32, NULL((void*)0), 0x00080000,
3348 "Axis Status Data Set: In Process", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3349 },
3350 { &hf_cip_axis_sts_dc_bus_unload,
3351 { "DC Bus Unload", "cipm.axis.dcunload",
3352 FT_BOOLEAN, 32, NULL((void*)0), 0x00100000,
3353 "Axis Status Data Set: DC Bus Unload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3354 },
3355 { &hf_cip_axis_sts_ac_pwr_loss,
3356 { "AC Power Loss", "cipm.axis.acpwrloss",
3357 FT_BOOLEAN, 32, NULL((void*)0), 0x00200000,
3358 "Axis Status Data Set: AC Power Loss", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3359 },
3360 { &hf_cip_axis_sts_pos_cntrl_mode,
3361 { "Pos Control Mode", "cipm.axis.poscntrl",
3362 FT_BOOLEAN, 32, NULL((void*)0), 0x00400000,
3363 "Axis Status Data Set: Position Control Mode", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3364 },
3365 { &hf_cip_axis_sts_vel_cntrl_mode,
3366 { "Vel Control Mode", "cipm.axis.velcntrl",
3367 FT_BOOLEAN, 32, NULL((void*)0), 0x00800000,
3368 "Axis Status Data Set: Velocity Control Mode", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3369 },
3370 { &hf_cip_axis_sts_trq_cntrl_mode,
3371 { "Torque Control Mode", "cipm.axis.trqcntrl",
3372 FT_BOOLEAN, 32, NULL((void*)0), 0x01000000,
3373 "Axis Status Data Set: Torque Control Mode", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3374 },
3375
3376 // Attribute #740 - Axis Status 2.
3377 { &hf_cip_axis_status2,
3378 { "Axis Status 2", "cipm.axisstatus2",
3379 FT_UINT32, BASE_HEX, NULL((void*)0), 0,
3380 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3381 },
3382 { &hf_cip_axis_sts2_motor,
3383 { "Motoring", "cipm.axis2.motor",
3384 FT_BOOLEAN, 32, NULL((void*)0), 0x00000001,
3385 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3386 },
3387 { &hf_cip_axis_sts2_regenerate,
3388 { "Regenerating", "cipm.axis2.regen",
3389 FT_BOOLEAN, 32, NULL((void*)0), 0x00000002,
3390 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3391 },
3392 { &hf_cip_axis_sts2_ride_thru,
3393 { "Ride Thru", "cipm.axis2.ridethru",
3394 FT_BOOLEAN, 32, NULL((void*)0), 0x00000004,
3395 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3396 },
3397 { &hf_cip_axis_sts2_ac_line_sync,
3398 { "AC Line Sync", "cipm.axis2.acsync",
3399 FT_BOOLEAN, 32, NULL((void*)0), 0x00000008,
3400 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3401 },
3402 { &hf_cip_axis_sts2_bus_volt_lock,
3403 { "Bus Voltage Lock", "cipm.axis2.voltlock",
3404 FT_BOOLEAN, 32, NULL((void*)0), 0x00000010,
3405 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3406 },
3407 { &hf_cip_axis_sts2_react_pwr_only,
3408 { "Reactive Power Only Mode", "cipm.axis2.reactpwr",
3409 FT_BOOLEAN, 32, NULL((void*)0), 0x00000020,
3410 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3411 },
3412 { &hf_cip_axis_sts2_volt_ctrl_mode,
3413 { "Voltage Control Mode", "cipm.axis2.voltmode",
3414 FT_BOOLEAN, 32, NULL((void*)0), 0x00000040,
3415 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3416 },
3417 { &hf_cip_axis_sts2_pwr_loss,
3418 { "Power Loss", "cipm.axis2.pwrloss",
3419 FT_BOOLEAN, 32, NULL((void*)0), 0x00000080,
3420 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3421 },
3422 { &hf_cip_axis_sts2_ac_volt_sag,
3423 { "AC Line Voltage Sag", "cipm.axis2.voltsag",
3424 FT_BOOLEAN, 32, NULL((void*)0), 0x00000100,
3425 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3426 },
3427 { &hf_cip_axis_sts2_ac_phase_loss,
3428 { "AC Line Phase Loss", "cipm.axis2.phaseloss",
3429 FT_BOOLEAN, 32, NULL((void*)0), 0x00000200,
3430 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3431 },
3432 { &hf_cip_axis_sts2_ac_freq_change,
3433 { "AC Line Frequency Change", "cipm.axis2.freqchange",
3434 FT_BOOLEAN, 32, NULL((void*)0), 0x00000400,
3435 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3436 },
3437 { &hf_cip_axis_sts2_ac_sync_loss,
3438 { "AC Line Sync Loss", "cipm.axis2.syncloss",
3439 FT_BOOLEAN, 32, NULL((void*)0), 0x00000800,
3440 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3441 },
3442 { &hf_cip_axis_sts2_single_phase,
3443 { "Single Phase", "cipm.axis2.singlephase",
3444 FT_BOOLEAN, 32, NULL((void*)0), 0x00001000,
3445 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3446 },
3447
3448 { &hf_cip_axis_sts2_bus_volt_limit,
3449 { "Bus Voltage Limit", "cipm.axis2.bus_volt_limit",
3450 FT_BOOLEAN, 32, NULL((void*)0), 0x00002000,
3451 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3452 },
3453 { &hf_cip_axis_sts2_bus_volt_rate_limit,
3454 { "Bus Voltage Rate Limit", "cipm.axis2.bus_volt_rate_limit",
3455 FT_BOOLEAN, 32, NULL((void*)0), 0x00004000,
3456 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3457 },
3458 { &hf_cip_axis_sts2_active_current_rate_limit,
3459 { "Active Current Rate Limit", "cipm.axis2.active_current_rate_limit",
3460 FT_BOOLEAN, 32, NULL((void*)0), 0x00008000,
3461 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3462 },
3463 { &hf_cip_axis_sts2_reactive_current_rate_limit,
3464 { "Reactive Current Rate Limit", "cipm.axis2.reactive_current_rate_limit",
3465 FT_BOOLEAN, 32, NULL((void*)0), 0x00010000,
3466 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3467 },
3468 { &hf_cip_axis_sts2_reactive_pwr_limit,
3469 { "Reactive Power Limit", "cipm.axis2.reactive_pwr_limit",
3470 FT_BOOLEAN, 32, NULL((void*)0), 0x00020000,
3471 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3472 },
3473 { &hf_cip_axis_sts2_reactive_pwr_rate_limit,
3474 { "Reactive Power Rate Limit", "cipm.axis2.reactive_pwr_rate_limit",
3475 FT_BOOLEAN, 32, NULL((void*)0), 0x00040000,
3476 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3477 },
3478 { &hf_cip_axis_sts2_active_current_limit,
3479 { "Active Current Limit", "cipm.axis2.active_current_limit",
3480 FT_BOOLEAN, 32, NULL((void*)0), 0x00080000,
3481 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3482 },
3483 { &hf_cip_axis_sts2_reactive_current_limit,
3484 { "Reactive Current Limit", "cipm.axis2.reactive_current_limit",
3485 FT_BOOLEAN, 32, NULL((void*)0), 0x00100000,
3486 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3487 },
3488 { &hf_cip_axis_sts2_motor_pwr_limit,
3489 { "Motoring Power Limit", "cipm.axis2.motor_pwr_limit",
3490 FT_BOOLEAN, 32, NULL((void*)0), 0x00200000,
3491 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3492 },
3493 { &hf_cip_axis_sts2_regen_pwr_limit,
3494 { "Regenerative Power Limit", "cipm.axis2.regen_pwr_limit",
3495 FT_BOOLEAN, 32, NULL((void*)0), 0x00400000,
3496 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3497 },
3498 { &hf_cip_axis_sts2_convert_therm_limit,
3499 { "Converter Thermal Limit", "cipm.axis2.convert_therm_limit",
3500 FT_BOOLEAN, 32, NULL((void*)0), 0x00800000,
3501 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3502 },
3503
3504 { &hf_cip_act_pos,
3505 { "Actual Position", "cipm.actpos",
3506 FT_INT32, BASE_DEC, NULL((void*)0), 0,
3507 "Cyclic Data Set: Actual Position", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3508 },
3509 { &hf_cip_act_pos_64,
3510 { "Actual Position", "cipm.actpos_64",
3511 FT_INT64, BASE_DEC, NULL((void*)0), 0,
3512 "Cyclic Data Set: Actual Position", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3513 },
3514 { &hf_cip_act_vel,
3515 { "Actual Velocity", "cipm.actvel",
3516 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3517 "Cyclic Data Set: Actual Velocity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3518 },
3519 { &hf_cip_act_accel,
3520 { "Actual Acceleration", "cipm.actaccel",
3521 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3522 "Cyclic Data Set: Actual Acceleration", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3523 },
3524 { &hf_cip_pos_cmd,
3525 { "Position Command", "cipm.posfcmd",
3526 FT_DOUBLE, BASE_NONE, NULL((void*)0), 0,
3527 "Cyclic Data Set: Position Command (LREAL)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3528 },
3529 { &hf_cip_pos_cmd_int,
3530 { "Position Command", "cipm.posicmd",
3531 FT_INT32, BASE_DEC, NULL((void*)0), 0,
3532 "Cyclic Data Set: Position Command (DINT)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3533 },
3534 { &hf_cip_vel_cmd,
3535 { "Velocity Command", "cipm.velcmd",
3536 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3537 "Cyclic Data Set: Velocity Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3538 },
3539 { &hf_cip_accel_cmd,
3540 { "Acceleration Command", "cipm.accelcmd",
3541 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3542 "Cyclic Data Set: Acceleration Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3543 },
3544 { &hf_cip_trq_cmd,
3545 { "Torque Command", "cipm.torquecmd",
3546 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3547 "Cyclic Data Set: Torque Command", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3548 },
3549 { &hf_cip_pos_trim,
3550 { "Position Trim", "cipm.postrim",
3551 FT_INT32, BASE_DEC, NULL((void*)0), 0,
3552 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3553 },
3554 { &hf_cip_vel_trim,
3555 { "Velocity Trim", "cipm.veltrim",
3556 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3557 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3558 },
3559 { &hf_cip_accel_trim,
3560 { "Acceleration Trim", "cipm.acceltrim",
3561 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3562 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3563 },
3564 { &hf_cip_trq_trim,
3565 { "Torque Trim", "cipm.trqtrim",
3566 FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
3567 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3568 },
3569 { &hf_cip_data,
3570 { "Data", "cipm.data",
3571 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
3572 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3573 }
3574 };
3575
3576 /* Setup protocol subtree array, these will help Wireshark remember
3577 * if the subtree should be expanded as the user moves through packets */
3578 static int *ett[] = {
3579 &ett_cipmotion,
3580 &ett_cont_dev_header,
3581 &ett_control_status,
3582 &ett_node_control,
3583 &ett_node_status,
3584 &ett_time_data_set,
3585 &ett_inst_data_header,
3586 &ett_cyclic_data_block,
3587 &ett_cyclic_command_data,
3588 &ett_feedback_mode,
3589 &ett_connection_configuration_bits,
3590 &ett_control_mode,
3591 &ett_feedback_config,
3592 &ett_command_data_set,
3593 &ett_actual_data_set,
3594 &ett_status_data_set,
3595 &ett_interp_control,
3596 &ett_cyclic_rd_wt,
3597 &ett_event,
3598 &ett_event_check_ctrl,
3599 &ett_event_check_sts,
3600 &ett_service,
3601 &ett_get_axis_attribute,
3602 &ett_set_axis_attribute,
3603 &ett_get_axis_attr_list,
3604 &ett_set_axis_attr_list,
3605 &ett_set_cyclic_list,
3606 &ett_group_sync,
3607 &ett_axis_status_set,
3608 &ett_command_control,
3609 &ett_configuration_block
3610 };
3611
3612 static ei_register_info ei[] = {
3613 { &ei_format_rev_conn_pt, { "cipm.malformed.format_revision_mismatch", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Format Revision does not match Connection Point", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
3614 };
3615
3616 /* Create a CIP Motion protocol handle */
3617 proto_cipmotion = proto_register_protocol("Common Industrial Protocol, Motion", "CIP Motion", "cipm");
3618
3619 proto_cipmotion3 = proto_register_protocol_in_name_only(
3620 "Common Industrial Protocol, Motion - Rev 3",
3621 "CIP Motion - Rev 3",
3622 "cipm3",
3623 proto_cipmotion,
3624 FT_PROTOCOL);
3625
3626 /* Register the header fields with the protocol */
3627 proto_register_field_array(proto_cipmotion, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
3628
3629 /* Register the subtrees for the protocol dissection */
3630 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
3631
3632 expert_module_t* expert_cipm = expert_register_protocol(proto_cipmotion);
3633 expert_register_field_array(expert_cipm, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
3634
3635 module_t* cipm_module = prefs_register_protocol(proto_cipmotion, NULL((void*)0));
3636 prefs_register_bool_preference(cipm_module, "display_full_attribute_data",
3637 "Display full attribute data in the Service Data Block",
3638 "Whether the CIP Motion dissector always display the full raw attribute data bytes",
3639 &display_full_attribute_data);
3640
3641 cipmotion_handle = register_dissector("cipmotion", dissect_cipmotion, proto_cipmotion);
3642 cipmotion3_handle = register_dissector("cipmotion3", dissect_cipmotion3, proto_cipmotion3);
3643}
3644
3645void proto_reg_handoff_cipmotion(void)
3646{
3647 dissector_add_for_decode_as("cip.io", cipmotion_handle);
3648 dissector_add_for_decode_as("cip.io", cipmotion3_handle);
3649
3650 dissector_add_uint("cip.io.iface", CI_CLS_MOTION0x42, cipmotion_handle);
3651}
3652
3653/*
3654* Editor modelines - https://www.wireshark.org/tools/modelines.html
3655*
3656* Local variables:
3657* c-basic-offset: 3
3658* tab-width: 8
3659* indent-tabs-mode: nil
3660* End:
3661*
3662* ex: set shiftwidth=3 tabstop=8 expandtab:
3663* :indentSize=3:tabSize=8:noTabs=true:
3664*/