1 /* packet-sercosiii.c
2  * Routines for SERCOS III dissection
3  *
4  * Initial plugin code by,
5  * Bosch Rexroth
6  * Hilscher
7  *
8  * Hans-Peter Bock <hpbock@avaapgh.de>
9  *
10  * Convert to built-in dissector
11  *   Michael Mann * Copyright 2011
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * SPDX-License-Identifier: GPL-2.0-or-later
18  */
19 
20 #include "config.h"
21 
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include <epan/etypes.h>
25 
26 #define MAX_SERCOS_DEVICES (512)
27 #define MAX_SERCOS_ADDRESS (511)
28 #define SERCOS_SLAVE_GROUP_SIZE (128)
29 
30 #define COMMUNICATION_PHASE_0 (0x0)
31 #define COMMUNICATION_PHASE_1 (0x1)
32 #define COMMUNICATION_PHASE_2 (0x2)
33 #define COMMUNICATION_PHASE_3 (0x3)
34 #define COMMUNICATION_PHASE_4 (0x4)
35 
36 void proto_register_sercosiii(void);
37 void proto_reg_handoff_sercosiii(void);
38 
39 /* Initialize the protocol and registered fields */
40 static gint proto_siii = -1;
41 
42 /* Initialize the subtree pointers */
43 static gint ett_siii = -1;
44 static gint ett_siii_header = -1;
45 static gint ett_siii_mst = -1;
46 static gint ett_siii_mst_teltype = -1;
47 static gint ett_siii_mst_phase = -1;
48 static gint ett_siii_mdt = -1;
49 static gint ett_siii_mdt_svc = -1;
50 static gint ett_siii_mdt_devctrls = -1;
51 static gint ett_siii_mdt_version = -1;
52 static gint ett_siii_mdt_svc_channel = -1;
53 static gint ett_siii_mdt_dev_control = -1;
54 static gint ett_siii_mdt_devctrl = -1;
55 static gint ett_siii_mdt_svcctrl = -1;
56 static gint ett_siii_mdt_svcinfo = -1;
57 static gint ett_siii_at_svcstat = -1;
58 static gint ett_siii_at_svcinfo = -1;
59 static gint ett_siii_mdt_svch_data_error_info = -1;
60 static gint ett_siii_mdt_svch_data = -1;
61 static gint ett_siii_at_devstatus = -1;
62 static gint ett_siii_at_sercosaddress = -1;
63 static gint ett_siii_at = -1;
64 static gint ett_siii_at_svc = -1;
65 static gint ett_siii_at_sercos_address = -1;
66 static gint ett_siii_at_devstats = -1;
67 static gint ett_siii_at_svc_channel = -1;
68 static gint ett_siii_at_dev_status = -1;
69 static gint ett_siii_mdt_hp = -1;
70 static gint ett_siii_at_hp = -1;
71 static gint ett_siii_mdt_hp_ctrl = -1;
72 static gint ett_siii_mdt_hp_info = -1;
73 static gint ett_siii_at_hp_stat = -1;
74 static gint ett_siii_at_hp_info = -1;
75 static gint ett_siii_recognized_devices = -1;
76 
77 static gint hf_siii_mdt_version = -1;
78 static gint hf_siii_mdt_version_initprocvers = -1;
79 static gint hf_siii_mdt_version_num_mdt_at_cp1_2 = -1;
80 static gint hf_siii_mdt_version_switch_off_sercos_telegrams = -1;
81 static gint hf_siii_mdt_version_fast_cp_switch = -1;
82 static gint hf_siii_mdt_version_transmission_of_communication_parameters_mdt0_cp0 = -1;
83 static gint hf_siii_mdt_dev_control_top_control = -1;
84 static gint hf_siii_at_dev_control_ident = -1;
85 static gint hf_siii_mdt_dev_control_change_topology = -1;
86 static gint hf_siii_mdt_dev_control = -1;
87 static gint hf_siii_mst_channel = -1;
88 static gint hf_siii_mst_type = -1;
89 static gint hf_siii_mst_cyclecntvalid = -1;
90 static gint hf_siii_mst_telno = -1;
91 static gint hf_siii_mst_phase = -1;
92 static gint hf_siii_mst_cyclecnt = -1;
93 static gint hf_siii_mst_crc32 = -1;
94 static gint hf_siii_mdt_svch_dbe = -1;
95 static gint hf_siii_mdt_svch_eot = -1;
96 static gint hf_siii_mdt_svch_rw = -1;
97 static gint hf_siii_mdt_svch_mhs = -1;
98 static gint hf_siii_mdt_svch_info = -1;
99 static gint hf_siii_at_svch_valid = -1;
100 static gint hf_siii_at_svch_error = -1;
101 static gint hf_siii_at_svch_busy = -1;
102 static gint hf_siii_at_svch_ahs = -1;
103 static gint hf_siii_at_svch_info = -1;
104 static gint hf_siii_mdt_svch_idn = -1;
105 static gint hf_siii_mdt_svch_ctrl = -1;
106 static gint hf_siii_at_svch_stat = -1;
107 /* static gint hf_siii_svch_data_telofs_telno = -1; */
108 /* static gint hf_siii_svch_data_telofs_mdt_at = -1; */
109 /* static gint hf_siii_svch_data_telofs_offset = -1; */
110 /* static gint hf_siii_svch_data_proccmd_proccmdexec = -1; */
111 /* static gint hf_siii_svch_data_proccmd_proccmd = -1; */
112 static gint hf_siii_at_cp0_support_functions = -1;
113 static gint hf_siii_at_cp0_device_address = -1;
114 static gint hf_siii_at_dev_status = -1;
115 static gint hf_siii_at_dev_status_commwarning = -1;
116 static gint hf_siii_at_dev_status_change_topology = -1;
117 static gint hf_siii_at_dev_status_top_status = -1;
118 static gint hf_siii_at_dev_status_inactive_port_status = -1;
119 static gint hf_siii_at_dev_status_errorconnection = -1;
120 static gint hf_siii_at_dev_status_slave_valid = -1;
121 static gint hf_siii_at_dev_status_proc_command_change = -1;
122 static gint hf_siii_at_dev_status_parameterization_level_active = -1;
123 static gint hf_siii_mdt_hotplug_address = -1;
124 static gint hf_siii_mdt_hp_ctrl = -1;
125 static gint hf_siii_mdt_hp_info = -1;
126 static gint hf_siii_at_hotplug_address = -1;
127 static gint hf_siii_at_hp_stat = -1;
128 static gint hf_siii_at_hp_info = -1;
129 static gint hf_siii_mdt_hotplug_control_param = -1;
130 static gint hf_siii_mdt_hotplug_control_svc_switch = -1;
131 static gint hf_siii_at_hotplug_status_param = -1;
132 static gint hf_siii_at_hotplug_status_hp0_finished = -1;
133 static gint hf_siii_at_hotplug_status_error = -1;
134 static gint hf_siii_service_channels = -1;
135 static gint hf_siii_device_controls = -1;
136 static gint hf_siii_device_status = -1;
137 static gint hf_siii_idn_code = -1;
138 static gint hf_siii_at_cp0_num_devices = -1;
139 static gint hf_siii_at_cp0_sercos_address = -1;
140 
141 static expert_field ei_siii_cp_unknown = EI_INIT;
142 
143 
144 /* Allow heuristic dissection */
145 static heur_dissector_list_t heur_subdissector_list;
146 
147 static const value_string siii_mdt_version_num_mdtat_cp1_2_text[]=
148 {
149   {0x00, "2 MDTs/ATs in CP1/2"},
150   {0x01, "4 MDTs/ATs in CP1/2"},
151   {0, NULL}
152 };
153 
154 static const true_false_string siii_mdt_version_fast_cp_switch_text = {
155   "Transmission of MST (MDT0) interrupted during CP switch for CPS delay time (120ms)",
156   "CPS delay time reduce to the re-configuration time of the master"
157 };
158 
159 
160 static const true_false_string siii_switch_off_sercos_telegram_text = {
161   "Industrial Ethernet devices not used by application",
162   "Industrial Ethernet devices used by application"
163 };
164 
165 static const true_false_string siii_mdt_version_initprocvers_text = {
166   "No remote address allocation",
167   "Remote address allocation"
168 };
169 
170 #if 0
171 static const value_string siii_svch_data_proccmd_proccmdexec_text[]=
172 {
173   {0, "Interrupt procedure command execution"},
174   {1, "Enable procedure command execution"},
175   {0, NULL}
176 };
177 
178 static const value_string siii_svch_data_proccmd_proccmd_text[]=
179 {
180   {0, "Cancel procedure command"},
181   {1, "Set procedure command"},
182   {0, NULL}
183 };
184 
185 static const value_string siii_svch_data_mdt_at_text[]=
186 {
187   {0, "AT-telegram"},
188   {1, "MDT-telegram"},
189   {0, NULL}
190 };
191 #endif
192 
193 #define IDN(SI, SE, type, paramset, datablock) ((SI<<24)|(SE<<16)|(type<<15)|(paramset<<12)|(datablock))
194 
195 static const value_string siii_mdt_idn_text[]=
196 {
197   {IDN(0,0,0,0,   0), "Dummy-Parameter"},
198   {IDN(0,0,0,0,   1), "Control unit cycle time (tNcyc)"},
199   {IDN(0,0,0,0,   2), "Communication cycle time (tScyc)"},
200   {IDN(0,0,0,0,  11), "Class 1 diagnostic"},
201   {IDN(0,0,0,0,  12), "Class 2 diagnostic"},
202   {IDN(0,0,0,0,  14), "Interface status"},
203   {IDN(0,0,0,0,  15), "Telegram Type"},
204   {IDN(0,0,0,0,  16), "Configuration list of AT"},
205   {IDN(0,0,0,0,  17), "IDN-list of all operation data"},
206   {IDN(0,0,0,0,  18), "IDN-list of operation data for CP2"},
207   {IDN(0,0,0,0,  19), "IDN-list of operation data for CP3"},
208   {IDN(0,0,0,0,  21), "IDN-list of invalid operation data for CP2"},
209   {IDN(0,0,0,0,  22), "IDN-list of invalid operation data for CP3"},
210   {IDN(0,0,0,0,  24), "Configuration list of MDT"},
211   {IDN(0,0,0,0,  25), "IDN-list of all procedure commands"},
212   {IDN(0,0,0,0,  26), "Configuration list for signal status word"},
213   {IDN(0,0,0,0,  27), "Configuration list for signal control word"},
214   {IDN(0,0,0,0,  28), "MST error counter"},
215   {IDN(0,0,0,0,  29), "MDT error counter"},
216   {IDN(0,0,0,0,  32), "Primary operation mode"},
217   {IDN(0,0,0,0,  36), "Velocity command value"},
218   {IDN(0,0,0,0,  37), "Additive velocity command value"},
219   {IDN(0,0,0,0,  38), "Positive velocity limit value"},
220   {IDN(0,0,0,0,  39), "Negative velocity limit value"},
221   {IDN(0,0,0,0,  40), "Velocity feedback value 1"},
222   {IDN(0,0,0,0,  41), "Homing velocity"},
223   {IDN(0,0,0,0,  42), "Homing acceleration"},
224   {IDN(0,0,0,0,  43), "Velocity polarity parameter"},
225   {IDN(0,0,0,0,  44), "Velocity data scaling type"},
226   {IDN(0,0,0,0,  45), "Velocity data scaling factor"},
227   {IDN(0,0,0,0,  46), "Velocity data scaling exponent"},
228   {IDN(0,0,0,0,  47), "Position command value"},
229   {IDN(0,0,0,0,  48), "Additive position command value"},
230   {IDN(0,0,0,0,  49), "Positive position limit value"},
231   {IDN(0,0,0,0,  50), "Negative position limit value"},
232   {IDN(0,0,0,0,  51), "Position feedback value 1 (motor feedback)"},
233   {IDN(0,0,0,0,  52), "Reference distance 1"},
234   {IDN(0,0,0,0,  53), "Position feedback value 2 (external feedback)"},
235   {IDN(0,0,0,0,  54), "Reference distance 2"},
236   {IDN(0,0,0,0,  55), "Position polarity parameter"},
237   {IDN(0,0,0,0,  57), "Position window"},
238   {IDN(0,0,0,0,  58), "Reversal clearance"},
239   {IDN(0,0,0,0,  59), "Position switch flag parameter"},
240   {IDN(0,0,0,0,  60), "Position switches (position switch points on 1-16)"},
241   {IDN(0,0,0,0,  76), "Position data scaling type"},
242   {IDN(0,0,0,0,  77), "Linear position data scaling factor"},
243   {IDN(0,0,0,0,  78), "Linear position data scaling exponent"},
244   {IDN(0,0,0,0,  79), "Rotational position resolution"},
245   {IDN(0,0,0,0,  80), "Torque command value"},
246   {IDN(0,0,0,0,  81), "Additive torque command value"},
247   {IDN(0,0,0,0,  82), "Positive torque limit value"},
248   {IDN(0,0,0,0,  83), "Negative torque limit value"},
249   {IDN(0,0,0,0,  84), "Torque feedback value"},
250   {IDN(0,0,0,0,  85), "Torque polarity parameter"},
251   {IDN(0,0,0,0,  86), "Torque/force data scaling type"},
252   {IDN(0,0,0,0,  91), "Bipolar velocity limit value"},
253   {IDN(0,0,0,0,  92), "Bipolar torque limit value"},
254   {IDN(0,0,0,0,  93), "Torque/force scaling data factor"},
255   {IDN(0,0,0,0,  94), "Torque/force scaling data exponent"},
256   {IDN(0,0,0,0,  95), "Diagnostic message"},
257   {IDN(0,0,0,0,  96), "Slave arrangement (SLKN)"},
258   {IDN(0,0,0,0,  97), "Mask class 2 diagnostic"},
259   {IDN(0,0,0,0,  98), "Mask class 3 diagnostic"},
260   {IDN(0,0,0,0,  99), "Reset class 1 diagnostic"},
261   {IDN(0,0,0,0, 100), "Velocity loop proportional gain"},
262   {IDN(0,0,0,0, 101), "Velocity loop integral action time"},
263   {IDN(0,0,0,0, 102), "Velocity loop differential time"},
264   {IDN(0,0,0,0, 103), "Modulo value"},
265   {IDN(0,0,0,0, 104), "Position loop KV-factor"},
266   {IDN(0,0,0,0, 105), "Position loop integral action time"},
267   {IDN(0,0,0,0, 106), "Current loop proportional gain 1"},
268   {IDN(0,0,0,0, 107), "Current loop integral action time 1"},
269   {IDN(0,0,0,0, 108), "Feedrate override"},
270   {IDN(0,0,0,0, 109), "Motor peak current"},
271   {IDN(0,0,0,0, 110), "Amplifier peak current"},
272   {IDN(0,0,0,0, 111), "Motor continuous stall current"},
273   {IDN(0,0,0,0, 112), "Amplifier rated current"},
274   {IDN(0,0,0,0, 113), "Maximum motor speed"},
275   {IDN(0,0,0,0, 114), "Load limit of the motor"},
276   {IDN(0,0,0,0, 115), "Position feedback 2 type"},
277   {IDN(0,0,0,0, 116), "Resolution of feedback 1"},
278   {IDN(0,0,0,0, 117), "Resolution of feedback 2"},
279   {IDN(0,0,0,0, 118), "Resolution of linear feedback"},
280   {IDN(0,0,0,0, 119), "Current loop proportional gain 2"},
281   {IDN(0,0,0,0, 120), "Current loop integral action time 2"},
282   {IDN(0,0,0,0, 121), "Input revolutions of load gear"},
283   {IDN(0,0,0,0, 122), "Output revolutions of load gear"},
284   {IDN(0,0,0,0, 123), "Feed constant"},
285   {IDN(0,0,0,0, 124), "Standstill window"},
286   {IDN(0,0,0,0, 125), "Velocity threshold (nx)"},
287   {IDN(0,0,0,0, 126), "Torque threshold (Tx)"},
288   {IDN(0,0,0,0, 127), "CP3 transition check"},
289   {IDN(0,0,0,0, 128), "CP4 transition check"},
290   {IDN(0,0,0,0, 129), "Manufacturer class 1 diagnostic"},
291   {IDN(0,0,0,0, 130), "Probe value 1 positive edge"},
292   {IDN(0,0,0,0, 131), "Probe value 1 negative edge"},
293   {IDN(0,0,0,0, 132), "Probe value 2 positive edge"},
294   {IDN(0,0,0,0, 133), "Probe value 2 negative edge"},
295   {IDN(0,0,0,0, 134), "Drive control"},
296   {IDN(0,0,0,0, 135), "Drive status"},
297   {IDN(0,0,0,0, 136), "Positive acceleration limit value"},
298   {IDN(0,0,0,0, 137), "Negative acceleration limit value"},
299   {IDN(0,0,0,0, 138), "Bipolar acceleration limit value"},
300   {IDN(0,0,0,0, 139), "Park axis procedure command"},
301   {IDN(0,0,0,0, 143), "SERCOS Interface version"},
302   {IDN(0,0,0,0, 144), "Signal status word"},
303   {IDN(0,0,0,0, 145), "Signal control word"},
304   {IDN(0,0,0,0, 146), "Control unit controlled homing procedure command"},
305   {IDN(0,0,0,0, 147), "Homing parameter"},
306   {IDN(0,0,0,0, 148), "Drive controlled homing procedure command"},
307   {IDN(0,0,0,0, 149), "Position drive stop procedure command"},
308   {IDN(0,0,0,0, 150), "Reference offset 1"},
309   {IDN(0,0,0,0, 151), "Reference offset 2"},
310   {IDN(0,0,0,0, 152), "Position spindle procedure command"},
311   {IDN(0,0,0,0, 153), "Spindle angle position"},
312   {IDN(0,0,0,0, 154), "Spindle positioning parameter"},
313   {IDN(0,0,0,0, 155), "Friction torque compensation"},
314   {IDN(0,0,0,0, 156), "Velocity feedback value 2"},
315   {IDN(0,0,0,0, 157), "Velocity window"},
316   {IDN(0,0,0,0, 158), "Power threshold (Px)"},
317   {IDN(0,0,0,0, 159), "Monitoring window"},
318   {IDN(0,0,0,0, 161), "Acceleration data scaling factor"},
319   {IDN(0,0,0,0, 162), "Acceleration data scaling exponent"},
320   {IDN(0,0,0,0, 163), "Weight counterbalance"},
321   {IDN(0,0,0,0, 164), "Acceleration feedback value 1"},
322   {IDN(0,0,0,0, 165), "Distance-coded reference marks A"},
323   {IDN(0,0,0,0, 166), "Distance-coded reference marks B"},
324   {IDN(0,0,0,0, 167), "Frequency limit of feedback 1"},
325   {IDN(0,0,0,0, 169), "Probe control"},
326   {IDN(0,0,0,0, 170), "Probing cycle procedure command"},
327   {IDN(0,0,0,0, 171), "Calculate displacement procedure command"},
328   {IDN(0,0,0,0, 172), "Displacement to the referenced system procedure command"},
329   {IDN(0,0,0,0, 173), "Marker position A"},
330   {IDN(0,0,0,0, 174), "Marker position B"},
331   {IDN(0,0,0,0, 175), "Displacement parameter 1"},
332   {IDN(0,0,0,0, 176), "Displacement parameter 2"},
333   {IDN(0,0,0,0, 177), "Absolute distance 1"},
334   {IDN(0,0,0,0, 178), "Absolute distance 2"},
335   {IDN(0,0,0,0, 179), "Probe status"},
336   {IDN(0,0,0,0, 180), "Spindle relative offset"},
337   {IDN(0,0,0,0, 181), "Manufacturer class 2 diagnostic"},
338   {IDN(0,0,0,0, 183), "Synchronization velocity window"},
339   {IDN(0,0,0,0, 184), "Synchronization velocity error limit"},
340   {IDN(0,0,0,0, 185), "Length of the configurable data record in the AT"},
341   {IDN(0,0,0,0, 186), "Length of the configurable data record in the MDT"},
342   {IDN(0,0,0,0, 187), "IDN list of configurable data in the AT"},
343   {IDN(0,0,0,0, 188), "IDN list of configurable data in the MDT"},
344   {IDN(0,0,0,0, 189), "Following distance"},
345   {IDN(0,0,0,0, 190), "Drive controlled gear engaging procedure command"},
346   {IDN(0,0,0,0, 191), "Cancel reference point procedure command"},
347   {IDN(0,0,0,0, 192), "IDN-list of all backup operation data"},
348   {IDN(0,0,0,0, 193), "Positioning jerk"},
349   {IDN(0,0,0,0, 194), "Acceleration command time"},
350   {IDN(0,0,0,0, 195), "Acceleration feedback value 2"},
351   {IDN(0,0,0,0, 196), "Motor rated current"},
352   {IDN(0,0,0,0, 197), "Set coordinate system procedure command"},
353   {IDN(0,0,0,0, 198), "Initial coordinate value"},
354   {IDN(0,0,0,0, 199), "Shift coordinate system procedure command"},
355   {IDN(0,0,0,0, 200), "Amplifier warning temperature"},
356   {IDN(0,0,0,0, 201), "Motor warning temperature"},
357   {IDN(0,0,0,0, 202), "Cooling error warning temperature"},
358   {IDN(0,0,0,0, 203), "Amplifier shut-down temperature"},
359   {IDN(0,0,0,0, 204), "Motor shut-down temperature"},
360   {IDN(0,0,0,0, 205), "Cooling error shut-down temperature"},
361   {IDN(0,0,0,0, 206), "Drive on delay time"},
362   {IDN(0,0,0,0, 207), "Drive off delay time"},
363   {IDN(0,0,0,0, 208), "Temperature data scaling type"},
364   {IDN(0,0,0,0, 209), "Lower adaptation limit"},
365   {IDN(0,0,0,0, 210), "Upper adaptation limit"},
366   {IDN(0,0,0,0, 211), "Adaptation proportional gain"},
367   {IDN(0,0,0,0, 212), "Adaptation integral action time"},
368   {IDN(0,0,0,0, 213), "Engaging dither amplitude"},
369   {IDN(0,0,0,0, 214), "Average engaging speed"},
370   {IDN(0,0,0,0, 215), "Engaging dither period"},
371   {IDN(0,0,0,0, 216), "Switch parameter set procedure command"},
372   {IDN(0,0,0,0, 217), "Parameter set preselection"},
373   {IDN(0,0,0,0, 218), "Gear-ration preselection"},
374   {IDN(0,0,0,0, 219), "IDN-list of parameter set"},
375   {IDN(0,0,0,0, 220), "Minimum spindle speed"},
376   {IDN(0,0,0,0, 221), "Maximum spindle speed"},
377   {IDN(0,0,0,0, 222), "Spindle positioning speed"},
378   {IDN(0,0,0,0, 223), "Drive controlled synchronous operation procedure command"},
379   {IDN(0,0,0,0, 224), "Lead Spindle Address"},
380   {IDN(0,0,0,0, 225), "Synchronous spindle revolutions"},
381   {IDN(0,0,0,0, 226), "Lead spindle revolutions"},
382   {IDN(0,0,0,0, 227), "Synchronous spindle revolutions"},
383   {IDN(0,0,0,0, 228), "Synchronization position window"},
384   {IDN(0,0,0,0, 229), "Synchronization position error limit"},
385   {IDN(0,0,0,0, 230), "Synchronization position offset"},
386   {IDN(0,0,0,0, 254), "Actual parameter set"},
387   {IDN(0,0,0,0, 255), "Actual gear ration"},
388   {IDN(0,0,0,0, 256), "Multiplication factor 1"},
389   {IDN(0,0,0,0, 257), "Multiplication factor 2"},
390   {IDN(0,0,0,0, 258), "Target position"},
391   {IDN(0,0,0,0, 259), "Positioning velocity"},
392   {IDN(0,0,0,0, 260), "Positioning acceleration"},
393   {IDN(0,0,0,0, 261), "Coarse position window"},
394   {IDN(0,0,0,0, 262), "Load defaults procedure command"},
395   {IDN(0,0,0,0, 263), "Load working memory procedure command"},
396   {IDN(0,0,0,0, 264), "Backup working memory procedure command"},
397   {IDN(0,0,0,0, 265), "Language selection"},
398   {IDN(0,0,0,0, 266), "List of available languages"},
399   {IDN(0,0,0,0, 267), "Password"},
400   {IDN(0,0,0,0, 268), "Angular setting"},
401   {IDN(0,0,0,0, 269), "Storage mode"},
402   {IDN(0,0,0,0, 270), "IDN-list of selected backup operation data"},
403   {IDN(0,0,0,0, 272), "Velocity window percentage"},
404   {IDN(0,0,0,0, 273), "Maximum drive off delay time"},
405   {IDN(0,0,0,0, 275), "Coordinate offset value"},
406   {IDN(0,0,0,0, 276), "Return to Modulo range procedure command"},
407   {IDN(0,0,0,0, 277), "Position feedback 1 type"},
408   {IDN(0,0,0,0, 278), "Maximum travel range"},
409   {IDN(0,0,0,0, 279), "IDN list of password protected data"},
410   {IDN(0,0,0,0, 280), "Underflow threshold"},
411   {IDN(0,0,0,0, 282), "Positioning command value"},
412   {IDN(0,0,0,0, 283), "Current coordinate offset"},
413   {IDN(0,0,0,0, 292), "List of supported operation modes"},
414   {IDN(0,0,0,0, 293), "Selectively backup working memory procedure command"},
415   {IDN(0,0,0,0, 294), "Divider modulo value"},
416   {IDN(0,0,0,0, 295), "Drive enable delay time"},
417   {IDN(0,0,0,0, 296), "Velocity feed forward gain"},
418   {IDN(0,0,0,0, 297), "Homing distance"},
419   {IDN(0,0,0,0, 298), "Suggest home switch distance"},
420   {IDN(0,0,0,0, 299), "Home switch offset 1"},
421   {IDN(0,0,0,0, 300), "Real-time control bit 1"},
422   {IDN(0,0,0,0, 301), "Allocation of real-time control bit 1",},
423   {IDN(0,0,0,0, 302), "Real-time control bit 2"},
424   {IDN(0,0,0,0, 303), "Allocation of real-time control bit 2"},
425   {IDN(0,0,0,0, 304), "Real-time status bit 1"},
426   {IDN(0,0,0,0, 305), "Allocation of real-time status bit 1"},
427   {IDN(0,0,0,0, 306), "Real-time status-bit 2"},
428   {IDN(0,0,0,0, 307), "Allocation of real-time status bit 2"},
429   {IDN(0,0,0,0, 308), "Synchronization operation status"},
430   {IDN(0,0,0,0, 309), "Synchronization error status"},
431   {IDN(0,0,0,0, 310), "Overload warning"},
432   {IDN(0,0,0,0, 311), "Amplifier overtemperature warning"},
433   {IDN(0,0,0,0, 312), "Motor overtemperature warning"},
434   {IDN(0,0,0,0, 313), "Cooling error warning"},
435   {IDN(0,0,0,0, 315), "Positioning velocity higher than n Limit"},
436   {IDN(0,0,0,0, 323), "Target position outside of travel range"},
437   {IDN(0,0,0,0, 326), "Parameter checksum"},
438   {IDN(0,0,0,0, 327), "IDN list of checksum parameter"},
439   {IDN(0,0,0,0, 328), "Bit number allocation list for signal status word"},
440   {IDN(0,0,0,0, 329), "Bit number allocation list for signal control word"},
441   {IDN(0,0,0,0, 330), "Status 'nfeedback = ncommand'"},
442   {IDN(0,0,0,0, 331), "Status 'nfeedback = 0'"},
443   {IDN(0,0,0,0, 332), "Status 'nfeedback less then nx'"},
444   {IDN(0,0,0,0, 333), "Status 'T higher than Tx'"},
445   {IDN(0,0,0,0, 334), "Status 'T greater than Tlimit '"},
446   {IDN(0,0,0,0, 335), "Status 'ncommand greater than nlimit'"},
447   {IDN(0,0,0,0, 336), "Status 'In position'"},
448   {IDN(0,0,0,0, 337), "Status 'P greater Px'"},
449   {IDN(0,0,0,0, 338), "Status 'Position feedback = active target position'"},
450   {IDN(0,0,0,0, 339), "Status 'nfeedback less than minimum spindle speed'"},
451   {IDN(0,0,0,0, 340), "Status 'nfeedback exceeds maximum spindle speed'"},
452   {IDN(0,0,0,0, 341), "Status 'In Coarse position'"},
453   {IDN(0,0,0,0, 342), "Status 'Target position attained'"},
454   {IDN(0,0,0,0, 343), "Status 'Interpolator halted'"},
455   {IDN(0,0,0,0, 346), "Positioning control"},
456   {IDN(0,0,0,0, 347), "Velocity error"},
457   {IDN(0,0,0,0, 348), "Acceleration feed forward gain"},
458   {IDN(0,0,0,0, 349), "Bipolar jerk limit"},
459   {IDN(0,0,0,0, 356), "Distance home switch - marker puls"},
460   {IDN(0,0,0,0, 357), "Marker pulse distance"},
461   {IDN(0,0,0,0, 358), "Home switch offset 2"},
462   {IDN(0,0,0,0, 359), "Positioning deceleration"},
463   {IDN(0,0,0,0, 360), "MDT data container"},
464   {IDN(0,0,0,0, 362), "MDT data container A list index"},
465   {IDN(0,0,0,0, 364), "AT data container A1"},
466   {IDN(0,0,0,0, 366), "AT data container A list index"},
467   {IDN(0,0,0,0, 368), "Data container A pointer"},
468   {IDN(0,0,0,0, 370), "MDT data container A/B configuration list"},
469   {IDN(0,0,0,0, 371), "AT data container A/B configuration list"},
470   {IDN(0,0,0,0, 372), "Drive Halt acceleration bipolar"},
471   {IDN(0,0,0,0, 377), "Velocity feedback monitoring window"},
472   {IDN(0,0,0,0, 378), "Absolute encoder range 1"},
473   {IDN(0,0,0,0, 379), "Absolute encoder range 2"},
474   {IDN(0,0,0,0, 380), "DC bus voltage"},
475   {IDN(0,0,0,0, 381), "DC bus current"},
476   {IDN(0,0,0,0, 382), "DC bus power"},
477   {IDN(0,0,0,0, 383), "Motor temperature"},
478   {IDN(0,0,0,0, 384), "Amplifier temperature"},
479   {IDN(0,0,0,0, 385), "Active power"},
480   {IDN(0,0,0,0, 386), "Active position feedback value"},
481   {IDN(0,0,0,0, 387), "Power overload"},
482   {IDN(0,0,0,0, 388), "Braking current limit"},
483   {IDN(0,0,0,0, 389), "Effective current"},
484   {IDN(0,0,0,0, 390), "DiagnosticNumber"},
485   {IDN(0,0,0,0, 391), "Position feedback monitoring window"},
486   {IDN(0,0,0,0, 392), "Velocity feedback filter"},
487   {IDN(0,0,0,0, 393), "Command value mode"},
488   {IDN(0,0,0,0, 398), "IDN list of configurable real-time/status bits"},
489   {IDN(0,0,0,0, 399), "IDN list of configurable real-time/control bits"},
490   {IDN(0,0,0,0, 400), "Home switch"},
491   {IDN(0,0,0,0, 401), "Probe 1"},
492   {IDN(0,0,0,0, 402), "Probe 2"},
493   {IDN(0,0,0,0, 403), "Position feedback value status"},
494   {IDN(0,0,0,0, 404), "Position command value status"},
495   {IDN(0,0,0,0, 405), "Probe 1 enable"},
496   {IDN(0,0,0,0, 406), "Probe 2 enable"},
497   {IDN(0,0,0,0, 407), "Homing enable"},
498   {IDN(0,0,0,0, 408), "Reference marker pulse registered"},
499   {IDN(0,0,0,0, 409), "Probe 1 positive latched"},
500   {IDN(0,0,0,0, 410), "Probe 1 negative latched"},
501   {IDN(0,0,0,0, 411), "Probe 2 positive latched"},
502   {IDN(0,0,0,0, 412), "Probe 2 negative latched"},
503   {IDN(0,0,0,0, 413), "Bit number allocation of real-time control bit 1"},
504   {IDN(0,0,0,0, 414), "Bit number allocation of real-time control bit 2"},
505   {IDN(0,0,0,0, 415), "Bit number allocation of real-time status bit 1"},
506   {IDN(0,0,0,0, 416), "Bit number allocation of real-time status bit 2"},
507   {IDN(0,0,0,0, 417), "Positioning velocity threshold in modulo mode"},
508   {IDN(0,0,0,0, 418), "Target position window in modulo mode"},
509   {IDN(0,0,0,0, 419), "Positioning acknowledge"},
510   {IDN(0,0,0,0, 420), "Activate parameterization level procedure command (PL)"},
511   {IDN(0,0,0,0, 422), "Exit parameterization level procedure command"},
512   {IDN(0,0,0,0, 423), "IDN-list of invalid data for parameterization level"},
513   {IDN(0,0,0,0, 426), "Measuring data allocation 1"},
514   {IDN(0,0,0,0, 427), "Measuring data allocation 2"},
515   {IDN(0,0,0,0, 428), "IDN list of configurable measuring data"},
516   {IDN(0,0,0,0, 429), "Emergency stop deceleration"},
517   {IDN(0,0,0,0, 430), "Active target position"},
518   {IDN(0,0,0,0, 431), "Spindle positioning acceleration bipolar"},
519   {IDN(0,0,0,0, 437), "Positioning status"},
520   {IDN(0,0,0,0, 446), "Ramp reference velocity"},
521   {IDN(0,0,0,0, 447), "Set absolute position procedure command"},
522   {IDN(0,0,0,0, 448), "Set absolute position control word"},
523   {IDN(0,0,0,0, 460), "Position switches (position switch points off 1-16)"},
524   {IDN(0,0,0,0, 476), "Position switch control"},
525   {IDN(0,0,0,0, 477), "Position switch hysteresis"},
526   {IDN(0,0,0,0, 478), "Limit switch status"},
527   {IDN(0,0,0,0, 509), "Extended probe control"},
528   {IDN(0,0,0,0, 510), "Difference value probe 1"},
529   {IDN(0,0,0,0, 511), "Difference value probe 2"},
530   {IDN(0,0,0,0, 512), "Start position probing window 1"},
531   {IDN(0,0,0,0, 513), "End position probing window 1"},
532   {IDN(0,0,0,0, 514), "Start position probing window 2"},
533   {IDN(0,0,0,0, 515), "End position probing window 2"},
534   {IDN(0,0,0,0, 516), "Marker losses probe 1"},
535   {IDN(0,0,0,0, 517), "Marker losses probe 2"},
536   {IDN(0,0,0,0, 518), "Maximum marker losses probe 1"},
537   {IDN(0,0,0,0, 519), "Maximum marker losses probe 2"},
538   {IDN(0,0,0,0, 520), "Axis control word"},
539   {IDN(0,0,0,0, 521), "Axis status word"},
540   {IDN(0,0,0,0, 522), "Difference value 1 latched"},
541   {IDN(0,0,0,0, 523), "Difference value 2 latched"},
542   {IDN(0,0,0,0, 524), "Probe 1 delay positive"},
543   {IDN(0,0,0,0, 525), "Delay Negative Edge, Probe 1"},
544   {IDN(0,0,0,0, 526), "Delay positive Edge, Probe 2"},
545   {IDN(0,0,0,0, 527), "Delay Negative Edge, Probe 2"},
546   {IDN(0,0,0,0, 530), "Clamping torque"},
547   {IDN(0,0,0,0, 531), "Checksum for backup operation data"},
548   {IDN(0,0,0,0, 532), "Limit switch control"},
549   {IDN(0,0,0,0, 533), "Motor continuous stall torque/force"},
550   {IDN(0,0,0,0,1000), "SCP Type & Version"},
551   {IDN(0,0,0,0,1001), "SERCOS III: Control unit cycle time (tNcyc)"},
552   {IDN(0,0,0,0,1002), "SERCOS III: Communication cycle time (tScyc)"},
553   {IDN(0,0,0,0,1003), "SERCOS III: Number of successive MDT errors"},
554   {IDN(0,0,0,0,1005), "SERCOS III: Feedback value computation time (t5)"},
555   {IDN(0,0,0,0,1006), "SERCOS III: AT transmission starting time (t1)"},
556   {IDN(0,0,0,0,1007), "SERCOS III: Synchronization time (t8)"},
557   {IDN(0,0,0,0,1008), "SERCOS III: Command value valid time (t3)"},
558   {IDN(0,0,0,0,1009), "SERCOS III: Device Control offset in MDT"},
559   {IDN(0,0,0,0,1010), "SERCOS III: Length of MDT"},
560   {IDN(0,0,0,0,1011), "SERCOS III: Device Status offset in AT"},
561   {IDN(0,0,0,0,1012), "SERCOS III: Length of AT"},
562   {IDN(0,0,0,0,1013), "SERCOS III: SVC offset in MDT"},
563   {IDN(0,0,0,0,1014), "SERCOS III: SVC offset in AT"},
564   {IDN(0,0,0,0,1015), "SERCOS III: Ring delay"},
565   {IDN(0,0,0,0,1016), "SERCOS III: Slave delay"},
566   {IDN(0,0,0,0,1017), "SERCOS III: Transmission starting time IP channel"},
567   {IDN(0,0,0,0,1018), "SERCOS III: SYNC delay"},
568   {IDN(0,0,0,0,1019), "SERCOS III: MAC address"},
569   {IDN(0,0,0,0,1020), "SERCOS III: IP address"},
570   {IDN(0,0,0,0,1021), "SERCOS III: Network mask"},
571   {IDN(0,0,0,0,1022), "SERCOS III: Gateway address"},
572   {IDN(0,0,0,0,1023), "SERCOS III: Sync jitter"},
573   {IDN(0,0,0,0,1024), "SERCOS III: Ring control - node control"},
574   {IDN(0,0,0,0,1025), "SERCOS III: Ring status - node status"},
575   {IDN(0,0,0,0,1026), "SERCOS III: Hardware identification"},
576   {IDN(0,0,0,0,1028), "SERCOS III: Error counter MDT0 MST"},
577   {IDN(0,0,0,0,1029), "SERCOS III: Error counter MDT0-3"},
578   {IDN(0,0,0,0,1030), "SERCOS III: Error counter AT0-3"},
579   {IDN(0,0,0,0,1031), "Signal assignment Port 1 & Port 2"},
580   {IDN(0,0,0,0,1035), "Error counter Port1 and Port2"},
581   {IDN(0,0,0,0,1040), "SERCOSAddress"},
582   {IDN(0,0,0,0,1041), "AT Command value valid time (t9)"},
583   {IDN(0,0,0,0,1044), "Device Control"},
584   {IDN(0,0,0,0,1045), "Device Status"},
585   {IDN(0,0,0,0,1046), "IDN-list of SERCOS addresses in device"},
586   {IDN(0,0,0,0,1134), "SERCOS III: Device control"},
587   {IDN(0,0,0,0,1135), "SERCOS III: Device status"},
588   {IDN(1,0,0,0,1027), "Requested MTU"},
589   {IDN(2,0,0,0,1027), "Effective MTU"},
590   {0, NULL}
591 };
592 static value_string_ext siii_mdt_idn_text_ext = VALUE_STRING_EXT_INIT(siii_mdt_idn_text);
593 
594 static const value_string siii_mdt_svch_dbe_text[]=
595 {
596   {0x00, "Element 0: Closed SVC"},
597   {0x01, "Element 1: Opening IDN"},
598   {0x02, "Element 2: Name of operation data"},
599   {0x03, "Element 3: Attribute of operation data"},
600   {0x04, "Element 4: Unit of operation data"},
601   {0x05, "Element 5: Minimum value of operation data"},
602   {0x06, "Element 6: Maximum value of operation data"},
603   {0x07, "Element 7: Operation data"},
604   {0, NULL}
605 };
606 
607 static const true_false_string siii_mdt_svch_eot_text = {
608   "Transmission in progress",
609   "Last transmission"
610 };
611 
612 static const true_false_string siii_mdt_svch_rw_text = {
613   "Read SVC INFO",
614   "Write SVC INFO"
615 };
616 
617 static const value_string siii_mdt_devcontrol_topcontrol_text[]=
618 {
619   {0x00, "Fast Forward on P/S-Channel"},
620   {0x01, "Loopback on P-Channel and Fast Forward"},
621   {0x02, "Loopback on S-Channel and Fast Forward"},
622   {0, NULL}
623 };
624 
625 static const true_false_string siii_at_svch_error_text = {
626   "No error",
627   "Error in SVC"
628 };
629 
630 static const true_false_string siii_at_svch_busy_text = {
631   "Step finished, slave ready for new step",
632   "Step in process, new step not allowed"
633 };
634 
635 
636 static const value_string siii_mst_phase_text[]=
637 {
638   {0x00, "CP0"},
639   {0x01, "CP1"},
640   {0x02, "CP2"},
641   {0x03, "CP3"},
642   {0x04, "CP4"},
643   {0x80, "CP0 (Phase Change)"},
644   {0x81, "CP1 (Phase Change)"},
645   {0x82, "CP2 (Phase Change)"},
646   {0x83, "CP3 (Phase Change)"},
647   {0x84, "CP4 (Phase Change)"},
648   {0, NULL}
649 };
650 
651 #if 0
652 static const value_string siii_mst_teltype_text[]=
653 {
654   {0x00, "CP0"},
655   {0x01, "CP1"},
656   {0x02, "CP2"},
657   {0x03, "CP3"},
658   {0x04, "CP4"},
659   {0x80, "CP0 (Phase Change)"},
660   {0x81, "CP1 (Phase Change)"},
661   {0x82, "CP2 (Phase Change)"},
662   {0x83, "CP3 (Phase Change)"},
663   {0x84, "CP4 (Phase Change)"},
664   {0, NULL}
665 };
666 #endif
667 
668 static const value_string siii_mst_channel_text[]=
669 {
670   {0x00, "P-Telegram"},
671   {0x01, "S-Telegram"},
672   {0, NULL}
673 };
674 
675 static const value_string siii_mst_type_text[]=
676 {
677   {0x00, "MDT"},
678   {0x01, "AT"},
679   {0, NULL}
680 };
681 
682 static const value_string siii_at_devstatus_errorconnection_text[]=
683 {
684   {0x00, "Error-free connection"},
685   {0x01, "Error in the connection occurs"},
686   {0, NULL}
687 };
688 
689 static const value_string siii_at_devstatus_topstatus_text[]=
690 {
691   {0x00, "Fast Forward on P/S-Channel"},
692   {0x01, "Loopback on P-Channel and Fast Forward"},
693   {0x02, "Loopback on S-Channel and Fast Forward"},
694   {0, NULL}
695 };
696 
697 static const true_false_string siii_at_cp0_support_functions_text = {
698   "Slave doesn't support one or more of the requested functions",
699   "Slave supports all requested functions"
700 };
701 
702 static const value_string siii_at_devstatus_inactiveportstatus_text[]=
703 {
704   {0x00, "No link on port"},
705   {0x01, "Link on port"},
706   {0x02, "S III P-Telegram on port"},
707   {0x03, "S III S-Telegram on port"},
708   {0, NULL}
709 };
710 
711 static const value_string siii_at_dev_status_proc_command_change_text[]=
712 {
713   {0x00, "No change in procedure command acknowledgement"},
714   {0x01, "Changing procedure command acknowledgement"},
715   {0, NULL}
716 };
717 
718 
719 static const value_string siii_mdt_hotplug_control_functioncode_text[]=
720 {
721   {0x00, "No data"},
722   {0x01, "tScyc"},
723   {0x02, "t1"},
724   {0x03, "t6"},
725   {0x04, "t7"},
726   {0x05, "Communication Version"},
727   {0x06, "Communication timeout"},
728   {0x10, "MDT0 Length"},
729   {0x11, "MDT1 Length"},
730   {0x12, "MDT2 Length"},
731   {0x13, "MDT3 Length"},
732   {0x20, "AT0 Length"},
733   {0x21, "AT1 Length"},
734   {0x22, "AT2 Length"},
735   {0x23, "AT3 Length"},
736   {0x80, "MDT-SVC pointer"},
737   {0x81, "MDT-RTD pointer"},
738   {0x82, "AT-SVC pointer"},
739   {0x83, "AT-RTD pointer"},
740   {0, NULL}
741 };
742 static value_string_ext siii_mdt_hotplug_control_functioncode_text_ext =
743     VALUE_STRING_EXT_INIT(siii_mdt_hotplug_control_functioncode_text);
744 
745 static const value_string siii_mdt_hotplug_control_svc_switch_text[]=
746 {
747   {0, "Transmission via HP-field"},
748   {1, "Switch to SVC"},
749   {0, NULL}
750 };
751 
752 static const value_string siii_mdt_hotplug_status_ackcode_text[]=
753 {
754   {0x80, "MDT-SVC pointer"},
755   {0x81, "MDT-RTD pointer"},
756   {0x82, "AT-SVC pointer"},
757   {0x83, "AT-RTD pointer"},
758   {255, "Next Sercos Slave has same address"},
759   {0, NULL}
760 };
761 
762 static const value_string siii_at_hotplug_status_error_text[]=
763 {
764   {0, "Acknowledgement in HP-1"},
765   {1, "Error in HP-1"},
766   {0, NULL}
767 };
768 
769 
770 
771 
772 
dissect_siii_mst(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)773 static void dissect_siii_mst(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
774 {
775   proto_tree *subtree;
776   proto_tree *subtree2;
777 
778   subtree = proto_tree_add_subtree(tree, tvb, 0, 6, ett_siii_mst, NULL, "MST");
779 
780   subtree2 = proto_tree_add_subtree(subtree, tvb, 0, 1, ett_siii_mst_teltype, NULL, "Telegram Type");
781 
782   proto_tree_add_item(subtree2, hf_siii_mst_channel,       tvb, 0, 1, ENC_LITTLE_ENDIAN);
783   proto_tree_add_item(subtree2, hf_siii_mst_type,          tvb, 0, 1, ENC_LITTLE_ENDIAN);
784   proto_tree_add_item(subtree2, hf_siii_mst_cyclecntvalid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
785   proto_tree_add_item(subtree2, hf_siii_mst_telno,         tvb, 0, 1, ENC_LITTLE_ENDIAN);
786 
787   subtree2 = proto_tree_add_subtree(subtree, tvb, 1, 1, ett_siii_mst_phase, NULL, "Phase Field");
788 
789   proto_tree_add_item(subtree2, hf_siii_mst_phase,    tvb, 1, 1, ENC_LITTLE_ENDIAN);
790   proto_tree_add_item(subtree2, hf_siii_mst_cyclecnt, tvb, 1, 1, ENC_LITTLE_ENDIAN);
791   proto_tree_add_item(subtree, hf_siii_mst_crc32,     tvb, 2, 4, ENC_LITTLE_ENDIAN);
792 
793 }
794 
dissect_siii_mdt_hp(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)795 static void dissect_siii_mdt_hp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
796 {
797   proto_tree *subtree;
798 
799   static int * const ctrl_fields[] = {
800     &hf_siii_mdt_hotplug_control_svc_switch,
801     &hf_siii_mdt_hotplug_control_param,
802     NULL
803   };
804 
805   subtree = proto_tree_add_subtree(tree, tvb, 0, 8, ett_siii_mdt_hp, NULL, "Hot-Plug");
806 
807   proto_tree_add_item(subtree, hf_siii_mdt_hotplug_address, tvb, 0, 2, ENC_LITTLE_ENDIAN);
808 
809   proto_tree_add_bitmask(subtree, tvb, 2, hf_siii_mdt_hp_ctrl,
810                                    ett_siii_mdt_hp_ctrl, ctrl_fields, ENC_LITTLE_ENDIAN);
811 
812   proto_tree_add_item(subtree, hf_siii_mdt_hp_info, tvb, 4, 4, ENC_NA);
813 }
814 
dissect_siii_mdt_devctrl(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)815 static void dissect_siii_mdt_devctrl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
816 {
817   static int * const ctrl_fields[] = {
818     &hf_siii_at_dev_control_ident,
819     &hf_siii_mdt_dev_control_change_topology,
820     &hf_siii_mdt_dev_control_top_control,
821     NULL
822   };
823 
824   proto_tree_add_bitmask(tree, tvb, 0, hf_siii_mdt_dev_control,
825                                    ett_siii_mdt_devctrl, ctrl_fields, ENC_LITTLE_ENDIAN);
826 }
827 
dissect_siii_mdt_svc(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint devno _U_)828 static void dissect_siii_mdt_svc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint devno _U_) /* devno will be needed in later versions */
829 {
830   proto_tree *subtree;
831   proto_item *ti;
832 
833   static int * const svch_fields[] = {
834     &hf_siii_mdt_svch_dbe, /* data block element */
835     &hf_siii_mdt_svch_eot, /* end of transmission */
836     &hf_siii_mdt_svch_rw,  /* read or write */
837     &hf_siii_mdt_svch_mhs, /* master hand shake */
838     NULL
839   };
840 
841   guint16 svc_ctrl = tvb_get_letohs(tvb, 0); /* service channel header */
842   guint8  svc_dbe  = (svc_ctrl>>3) & 7;      /* accessed data block element */
843 
844   proto_tree_add_bitmask(tree, tvb, 0, hf_siii_mdt_svch_ctrl,
845                                    ett_siii_mdt_svcctrl, svch_fields, ENC_LITTLE_ENDIAN);
846 
847   ti = proto_tree_add_item(tree, hf_siii_mdt_svch_info, tvb, 2, 4, ENC_NA);
848 
849   if (1 == svc_dbe)
850   {
851     subtree = proto_item_add_subtree(ti, ett_siii_mdt_svcinfo);
852     proto_tree_add_item(subtree, hf_siii_idn_code, tvb, 2, 4, ENC_LITTLE_ENDIAN);
853     proto_tree_add_item(subtree, hf_siii_mdt_svch_idn, tvb, 2, 4, ENC_LITTLE_ENDIAN);
854   }
855 }
856 
dissect_siii_mdt_cp0(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)857 static void dissect_siii_mdt_cp0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
858 {
859   static int * const version_fields[] = {
860     &hf_siii_mdt_version_switch_off_sercos_telegrams,
861     &hf_siii_mdt_version_fast_cp_switch,
862     &hf_siii_mdt_version_transmission_of_communication_parameters_mdt0_cp0,
863     &hf_siii_mdt_version_num_mdt_at_cp1_2,
864     &hf_siii_mdt_version_initprocvers,
865     NULL
866   };
867 
868   proto_tree_add_bitmask(tree, tvb, 0, hf_siii_mdt_version,
869                                    ett_siii_mdt_version, version_fields, ENC_LITTLE_ENDIAN);
870 }
871 
dissect_siii_mdt_cp1_2(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint telno)872 static void dissect_siii_mdt_cp1_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint telno)
873 {
874   guint     devstart = telno * SERCOS_SLAVE_GROUP_SIZE; /* MDT0: slaves 0-127; MDT1: slaves 128-255; ... */
875   tvbuff_t *tvb_n;
876 
877   guint idx;
878   proto_tree *subtree;
879   proto_tree *subtree_svc;
880   proto_tree *subtree_devctrl;
881 
882   subtree_svc = proto_tree_add_subtree(tree, tvb, 0, SERCOS_SLAVE_GROUP_SIZE * 6, ett_siii_mdt_svc, NULL, "Service Channels");
883 
884   subtree_devctrl = proto_tree_add_subtree(tree, tvb, SERCOS_SLAVE_GROUP_SIZE * 6, 512, ett_siii_mdt_svc, NULL, "Device Control");
885 
886   for (idx = 0; idx < SERCOS_SLAVE_GROUP_SIZE; ++idx) /* each MDT of CP1/2 has data for 128 different slaves */
887   {
888     tvb_n = tvb_new_subset_length(tvb, 6 * idx, 6); /* subset for service channel data */
889 
890     subtree = proto_tree_add_subtree_format(subtree_svc, tvb_n, 0, 6, ett_siii_mdt_svc_channel, NULL, "Device %u", idx + devstart);
891     dissect_siii_mdt_svc(tvb_n, pinfo, subtree, idx + devstart);
892 
893     tvb_n = tvb_new_subset_length(tvb, SERCOS_SLAVE_GROUP_SIZE * 6 + 4 * idx, 2); /* subset for device control information */
894 
895     subtree = proto_tree_add_subtree_format(subtree_devctrl, tvb_n, 0, 2, ett_siii_mdt_dev_control, NULL, "Device %u", idx + devstart);
896 
897     dissect_siii_mdt_devctrl(tvb_n, pinfo, subtree);
898   }
899 }
900 
dissect_siii_mdt_cp3_4(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint telno)901 static void dissect_siii_mdt_cp3_4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint telno)
902 {
903   /* guint devstart _U_ = telno * SERCOS_SLAVE_GROUP_SIZE; */
904 
905   if (0 == telno) /* dissect hotplug field in MDT0 only */
906     dissect_siii_mdt_hp(tvb, pinfo, tree);
907 
908   /* offsets of service channel, device status and connections are unknown
909    * this data could be extracted from svc communication during CP2
910    */
911   proto_tree_add_item(tree, hf_siii_service_channels, tvb, 0, 0, ENC_NA);
912 
913   proto_tree_add_item(tree, hf_siii_device_controls, tvb, 0, 0, ENC_NA);
914 }
915 
dissect_siii_mdt(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)916 static void dissect_siii_mdt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
917 {
918   proto_tree *subtree;
919   tvbuff_t   *tvb_n;
920 
921   guint       t_phase;
922   guint       telno;
923 
924   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIII MDT");
925 
926   t_phase = (tvb_get_guint8(tvb, 1)&0x8F); /* read communication phase out of SERCOS III header */
927   telno   = (tvb_get_guint8(tvb, 0) & 0xF); /* read number of MDT out of SERCOS III header */
928 
929   if (t_phase & 0x80) /* communication phase switching in progress */
930   {
931     col_append_fstr(pinfo->cinfo, COL_INFO, " Phase=CP?s -> CP%u",
932           (t_phase&0x0f));
933   }
934   else /* communication as usual */
935   {
936     col_append_fstr(pinfo->cinfo, COL_INFO, " Phase=CP%u",
937           (t_phase&0x0f));
938   }
939 
940   subtree = proto_tree_add_subtree_format(tree, tvb, 0, -1, ett_siii_mdt, NULL, "MDT%u", telno);
941 
942   dissect_siii_mst(tvb, pinfo, subtree); /* dissect SERCOS III header */
943 
944   switch (t_phase) /* call the MDT dissector depending on the current communication phase */
945   {
946   case COMMUNICATION_PHASE_0: /* CP0 */
947     tvb_n = tvb_new_subset_length(tvb, 6, 40);
948     dissect_siii_mdt_cp0(tvb_n, pinfo, subtree);
949   break;
950 
951   case COMMUNICATION_PHASE_1: /* CP1 */
952   case COMMUNICATION_PHASE_2: /* CP2 */
953     tvb_n = tvb_new_subset_length(tvb, 6, 1280);
954     dissect_siii_mdt_cp1_2(tvb_n, pinfo, subtree, telno);
955   break;
956 
957   case COMMUNICATION_PHASE_3: /* CP3 */
958   case COMMUNICATION_PHASE_4: /* CP4 */
959     tvb_n = tvb_new_subset_remaining(tvb, 6);
960     dissect_siii_mdt_cp3_4(tvb_n, pinfo, subtree, telno);
961   break;
962 
963   default:
964     proto_tree_add_expert(tree, pinfo, &ei_siii_cp_unknown, tvb, 6, -1);
965   }
966 }
967 
968 
dissect_siii_at_svc(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint devno _U_)969 static void dissect_siii_at_svc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint devno _U_) /* devno will be used in later versions */
970 {
971   static int * const svch_fields[] = {
972     &hf_siii_at_svch_valid,
973     &hf_siii_at_svch_error,
974     &hf_siii_at_svch_busy,
975     &hf_siii_at_svch_ahs,
976     NULL
977   };
978 
979   proto_tree_add_bitmask(tree, tvb, 0, hf_siii_at_svch_stat,
980                                    ett_siii_at_svcstat, svch_fields, ENC_LITTLE_ENDIAN);
981 
982   proto_tree_add_item(tree, hf_siii_at_svch_info, tvb, 2, 4, ENC_NA);
983 }
984 
dissect_siii_at_devstat(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)985 static void dissect_siii_at_devstat(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
986 {
987   static int * const status[] = {
988     &hf_siii_at_dev_status_commwarning,
989     &hf_siii_at_dev_status_change_topology,
990     &hf_siii_at_dev_status_top_status,
991     &hf_siii_at_dev_status_inactive_port_status,
992     &hf_siii_at_dev_status_errorconnection,
993     &hf_siii_at_dev_status_slave_valid,
994     &hf_siii_at_dev_status_proc_command_change,
995     &hf_siii_at_dev_status_parameterization_level_active,
996     NULL
997   };
998 
999   proto_tree_add_bitmask(tree, tvb, 0, hf_siii_at_dev_status,
1000                                    ett_siii_at_devstatus, status, ENC_LITTLE_ENDIAN);
1001 }
1002 
dissect_siii_at_hp(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)1003 static void dissect_siii_at_hp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1004 {
1005   proto_tree *subtree;
1006 
1007   static int * const status[] = {
1008     &hf_siii_at_hotplug_status_error,
1009     &hf_siii_at_hotplug_status_hp0_finished,
1010     &hf_siii_at_hotplug_status_param,
1011     NULL
1012   };
1013 
1014   subtree = proto_tree_add_subtree(tree, tvb, 0, 8, ett_siii_at_hp, NULL, "Hot-Plug");
1015 
1016   proto_tree_add_item(subtree, hf_siii_at_hotplug_address,              tvb, 0, 2, ENC_LITTLE_ENDIAN);
1017 
1018   proto_tree_add_bitmask(subtree, tvb, 2, hf_siii_at_hp_stat, ett_siii_at_hp_stat, status, ENC_LITTLE_ENDIAN);
1019 
1020   proto_tree_add_item(subtree, hf_siii_at_hp_info,                      tvb, 4, 4, ENC_NA);
1021 }
1022 
dissect_siii_at_cp0(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)1023 static void dissect_siii_at_cp0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1024 {
1025   guint16     seqcnt;           /* sequence counter */
1026   guint16     tfield;           /* topology field for sercos addresses */
1027   guint16     i;
1028   proto_tree *subtree, *subtree2;
1029   proto_item* ti;
1030 
1031   subtree = proto_tree_add_subtree(tree, tvb, 0, 1024, ett_siii_recognized_devices, NULL, "Recognized Devices");
1032 
1033   /* check sequence count field */
1034   seqcnt = tvb_get_letohs(tvb, 0);
1035   proto_tree_add_uint(subtree, hf_siii_at_cp0_num_devices, tvb, 0, 2, (MAX_SERCOS_ADDRESS & seqcnt)-1);
1036 
1037   /* check SERCOS address of each topology field */
1038   for (i = 1; i < MAX_SERCOS_DEVICES; ++i)
1039   {
1040     tfield = tvb_get_letohs(tvb, i*2);
1041 
1042     if (tfield == 0xFFFF)
1043     {
1044       proto_tree_add_uint_format(subtree, hf_siii_at_cp0_sercos_address, tvb, i*2, 2, 0xFFFF, "Sercos Address %u: No Device", i);
1045     }
1046     else
1047     {
1048       ti = proto_tree_add_uint_format(subtree, hf_siii_at_cp0_sercos_address, tvb, i*2, 2, (tfield & MAX_SERCOS_ADDRESS), "Sercos Address %u: %u", i, (tfield & MAX_SERCOS_ADDRESS));
1049       subtree2  = proto_item_add_subtree(ti, ett_siii_at_sercos_address);
1050       proto_tree_add_item(subtree2, hf_siii_at_cp0_support_functions,  tvb, i*2, 2, ENC_LITTLE_ENDIAN);
1051       proto_tree_add_item(subtree2, hf_siii_at_cp0_device_address,     tvb, i*2, 2, ENC_LITTLE_ENDIAN);
1052     }
1053   }
1054 }
1055 
dissect_siii_at_cp1_2(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint telno)1056 static void dissect_siii_at_cp1_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint telno)
1057 {
1058   guint     devstart = telno * SERCOS_SLAVE_GROUP_SIZE; /* AT0: slaves 0-127; AT1: slaves 128-255; ... */
1059   tvbuff_t *tvb_n;
1060 
1061   guint idx;
1062 
1063   proto_tree *subtree;
1064   proto_tree *subtree_svc;
1065   proto_tree *subtree_devstat;
1066 
1067   subtree_svc = proto_tree_add_subtree(tree, tvb, 0, SERCOS_SLAVE_GROUP_SIZE * 6, ett_siii_at_svc, NULL, "Service Channel");
1068 
1069   subtree_devstat = proto_tree_add_subtree(tree, tvb, SERCOS_SLAVE_GROUP_SIZE * 6, 512, ett_siii_at_devstats, NULL, "Device Status");
1070 
1071   for (idx = 0; idx < SERCOS_SLAVE_GROUP_SIZE; ++idx) /* each AT of CP1/2 has data of 128 different slaves */
1072   {
1073     tvb_n = tvb_new_subset_length(tvb, 6 * idx, 6); /* subset for service channel data */
1074 
1075     subtree = proto_tree_add_subtree_format(subtree_svc, tvb_n, 0, 6, ett_siii_at_svc_channel, NULL, "Device %u", idx + devstart);
1076     dissect_siii_at_svc(tvb_n, pinfo, subtree, idx + devstart);
1077 
1078     tvb_n = tvb_new_subset_length(tvb, SERCOS_SLAVE_GROUP_SIZE * 6 + 4 * idx, 2); /* subset for device status information */
1079 
1080     subtree = proto_tree_add_subtree_format(subtree_devstat, tvb_n, 0, 2, ett_siii_at_dev_status, NULL, "Device %u", idx + devstart);
1081     dissect_siii_at_devstat(tvb_n, pinfo, subtree);
1082   }
1083 }
1084 
dissect_siii_at_cp3_4(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint telno)1085 static void dissect_siii_at_cp3_4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint telno)
1086 {
1087   if (0 == telno) /* dissect hotplug field in AT0 only */
1088     dissect_siii_at_hp(tvb, pinfo, tree);
1089 
1090   /* offsets of service channel, device status and connections are unknown
1091    * this data could be extracted from svc communication during CP2
1092    */
1093   proto_tree_add_item(tree, hf_siii_service_channels, tvb, 0, 0, ENC_NA);
1094   proto_tree_add_item(tree, hf_siii_device_status, tvb, 0, 0, ENC_NA);
1095 }
1096 
1097 
dissect_siii_at(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)1098 static void dissect_siii_at(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1099 {
1100   proto_tree *subtree;
1101   tvbuff_t   *tvb_n;
1102 
1103   guint8      phase;
1104   guint       telno;
1105 
1106   phase = (tvb_get_guint8(tvb, 1)&0x8F); /* read communication phase out of SERCOS III header*/
1107   telno = (tvb_get_guint8(tvb, 0) & 0xF); /* read number of AT out of SERCOS III header */
1108 
1109   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIII AT");
1110 
1111   if (phase & 0x80) /* communication phase switching in progress */
1112   {
1113     col_append_fstr(pinfo->cinfo, COL_INFO, " Phase=CP?s -> CP%u",
1114           (phase&0x0f));
1115   }
1116   else /* communication as usual */
1117   {
1118      col_append_fstr(pinfo->cinfo, COL_INFO, " Phase=CP%u",
1119           (phase&0x0f));
1120   }
1121 
1122   subtree = proto_tree_add_subtree_format(tree, tvb, 0, -1, ett_siii_at, NULL, "AT%u", telno);
1123 
1124   dissect_siii_mst(tvb, pinfo, subtree); /* dissect SERCOS III header */
1125 
1126     switch (phase) /* call the AT dissector depending on the current communication phase */
1127     {
1128     case COMMUNICATION_PHASE_0: /* CP0 */
1129       tvb_n = tvb_new_subset_length(tvb, 6, 1024);
1130       dissect_siii_at_cp0(tvb_n, pinfo, subtree);
1131     break;
1132 
1133     case COMMUNICATION_PHASE_1: /* CP1 */
1134     case COMMUNICATION_PHASE_2: /* CP2 */
1135       tvb_n = tvb_new_subset_length(tvb, 6, 1280);
1136       dissect_siii_at_cp1_2(tvb_n, pinfo, subtree, telno);
1137     break;
1138 
1139     case COMMUNICATION_PHASE_3: /* CP3 */
1140     case COMMUNICATION_PHASE_4: /* CP4 */
1141       tvb_n = tvb_new_subset_remaining(tvb, 6);
1142       dissect_siii_at_cp3_4(tvb_n, pinfo, subtree, telno);
1143     break;
1144 
1145     default:
1146       proto_tree_add_expert(tree, pinfo, &ei_siii_cp_unknown, tvb, 6, -1);
1147     break;
1148     }
1149 }
1150 
1151 /* Main dissector entry */
1152 static int
dissect_siii(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1153 dissect_siii(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1154 {
1155   proto_item *ti;
1156   proto_tree *siii_tree;
1157   guint       type;
1158   const char *tel_ch   = "?";
1159   const char *tel_type = "?";
1160   guint       tel_no   = 0;
1161   heur_dtbl_entry_t *hdtbl_entry;
1162 
1163   /* setup columns */
1164   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SERCOS III V1.1");
1165   col_clear(pinfo->cinfo, COL_INFO);
1166 
1167   /*
1168    * In case the packet is a protocol encoded in the basic SercosIII transport stream,
1169    * give that protocol a chance to make a heuristic dissection, before we continue
1170    * to dissect it as a normal SercosIII packet.
1171    */
1172   if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, NULL))
1173     return tvb_captured_length(tvb);
1174 
1175   /* check what we got on our hand */
1176   type = tvb_get_guint8(tvb, 0);
1177   if (type & 0x80) /* primary or secondary channel */
1178     tel_ch = "S";
1179   else
1180     tel_ch = "P";
1181 
1182   if (type & 0x40) /* master data telegram (mdt) or slave telegram (at) */
1183     tel_type = "AT ";
1184   else
1185     tel_type = "MDT";
1186 
1187   tel_no = type &0xF; /* even though it's reserved (the V1.1 spec states that it is reserved for additional MDT/AT) */
1188 
1189   col_append_fstr(pinfo->cinfo, COL_INFO, "%s%u Channel=%s", tel_type, tel_no, tel_ch);
1190 
1191   ti = proto_tree_add_item(tree, proto_siii, tvb, 0, -1, ENC_NA);
1192 
1193   siii_tree = proto_item_add_subtree(ti, ett_siii);
1194 
1195    /* enter the specific dissector for AT or MDT */
1196   if (type & 0x40)
1197     dissect_siii_at(tvb, pinfo, siii_tree);
1198   else
1199     dissect_siii_mdt(tvb, pinfo, siii_tree);
1200 
1201   return tvb_captured_length(tvb);
1202 }
1203 
1204 static void
sercosiii_idn_code_format(gchar * result,guint32 svc_info)1205 sercosiii_idn_code_format( gchar *result, guint32 svc_info )
1206 {
1207    g_snprintf( result, ITEM_LABEL_LENGTH, "%c-%u-%04d.%d.%d",
1208        ((0xFFFF & svc_info)>>15)?'P':'S', /* private or sercos IDN */
1209       (svc_info>>12)&7,                  /* parameter record */
1210       (svc_info&4095),                   /* IDN */
1211       (svc_info>>24) & 0xFF,             /* structure index */
1212       (svc_info>>16) & 0xFF);            /* structure element */
1213 }
1214 
1215 void
proto_register_sercosiii(void)1216 proto_register_sercosiii(void)
1217 {
1218   static hf_register_info hf[] = {
1219 
1220     { &hf_siii_mdt_version,
1221       { "Communication Version", "siii.mdt.version",
1222       FT_UINT32, BASE_HEX, NULL, 0,
1223       NULL, HFILL }
1224     },
1225     { &hf_siii_mdt_version_num_mdt_at_cp1_2,
1226       { "Number of MDTs and ATS in CP1 and CP2", "siii.mdt.version.num_mdt_at_cp1_2",
1227       FT_UINT32, BASE_HEX, VALS(siii_mdt_version_num_mdtat_cp1_2_text), 0x30000,
1228       NULL, HFILL }
1229     },
1230     { &hf_siii_mdt_version_transmission_of_communication_parameters_mdt0_cp0,
1231       { "Transmission of Communication parameters", "siii.mdt.version.mdt0_cp0_transm_comm_parameter",
1232       FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x100000,
1233       NULL, HFILL }
1234     },
1235     { &hf_siii_mdt_version_fast_cp_switch,
1236       { "Fast CP switch", "siii.mdt.version.mdt0_cp0_fast_cp_switch",
1237       FT_BOOLEAN, 32, TFS(&siii_mdt_version_fast_cp_switch_text), 0x200000,
1238       NULL, HFILL }
1239     },
1240 
1241     { &hf_siii_mdt_version_switch_off_sercos_telegrams,
1242       { "Switch off Sercos III telegrams", "siii.mdt.version.mdt0_cp0_switch_off_sercos_telegram",
1243       FT_BOOLEAN, 32, TFS(&siii_switch_off_sercos_telegram_text), 0x400000,
1244       NULL, HFILL }
1245     },
1246     { &hf_siii_mdt_version_initprocvers,
1247       { "Initialization Procedure Version Number", "siii.mdt.version.initprocvers",
1248       FT_BOOLEAN, 32, TFS(&siii_mdt_version_initprocvers_text), 0xFF00,
1249       NULL, HFILL }
1250     },
1251 
1252     { &hf_siii_mdt_dev_control_top_control,
1253       { "Topology Control", "siii.mdt.devcontrol.topcontrol",
1254       FT_UINT16, BASE_DEC, VALS(siii_mdt_devcontrol_topcontrol_text), 3<<(12),
1255       NULL, HFILL }
1256     },
1257     { &hf_siii_at_dev_control_ident,
1258       { "Identification", "siii.mdt.devcontrol.identrequest",
1259       FT_UINT16, BASE_DEC, NULL, 0x8000,
1260       NULL, HFILL }
1261     },
1262     { &hf_siii_mdt_dev_control_change_topology,
1263       { "Changing Topology", "siii.mdt.devcontrol.topologychange",
1264       FT_UINT16, BASE_DEC, NULL, 1<<14,
1265       NULL, HFILL }
1266     },
1267     { &hf_siii_mdt_dev_control,
1268       { "Word", "siii.mdt.devcontrol",
1269       FT_UINT16, BASE_DEC, NULL, 0,
1270       NULL, HFILL }
1271     },
1272 
1273     { &hf_siii_at_dev_status,
1274       { "Word", "siii.at.devstatus",
1275       FT_UINT16, BASE_HEX, NULL, 0,
1276       NULL, HFILL }
1277     },
1278 
1279     { &hf_siii_at_dev_status_commwarning,
1280       { "Communication Warning", "siii.at.devstatus.commwarning",
1281       FT_UINT16, BASE_DEC, NULL, 1<<15,
1282       NULL, HFILL }
1283     },
1284 
1285     { &hf_siii_at_cp0_support_functions,
1286       { "Support of requested functions", "siii.at.supfunctions",
1287       FT_BOOLEAN, 16, TFS(&siii_at_cp0_support_functions_text), 1<<15,
1288       NULL, HFILL }
1289     },
1290 
1291     { &hf_siii_at_cp0_device_address,
1292       { "Sercos Address", "siii.at.sercosaddress",
1293       FT_UINT16, BASE_DEC, NULL, MAX_SERCOS_ADDRESS,
1294       NULL, HFILL }
1295     },
1296 
1297     { &hf_siii_at_dev_status_change_topology,
1298       { "Topology Change", "siii.at.devstatus.topologychanged",
1299       FT_UINT16, BASE_DEC, NULL, 1<<14,
1300       NULL, HFILL }
1301     },
1302     { &hf_siii_at_dev_status_top_status,
1303       { "Topology Status", "siii.at.devstatus.topstatus",
1304       FT_UINT16, BASE_DEC, VALS(siii_at_devstatus_topstatus_text), 0x3<<(12),
1305       NULL, HFILL }
1306     },
1307     { &hf_siii_at_dev_status_inactive_port_status,
1308       { "Port 1 Status", "siii.at.devstatus.inactportstatus",
1309       FT_UINT16, BASE_DEC, VALS(siii_at_devstatus_inactiveportstatus_text), 0x3<<(10),
1310       NULL, HFILL }
1311     },
1312     { &hf_siii_at_dev_status_errorconnection,
1313       { "Topology Status", "siii.at.devstatus.errorconnection",
1314       FT_UINT16, BASE_DEC, VALS(siii_at_devstatus_errorconnection_text), 1<<9,
1315       NULL, HFILL }
1316     },
1317     { &hf_siii_at_dev_status_slave_valid,
1318       { "Slave data valid", "siii.at.devstatus.slavevalid",
1319       FT_UINT16, BASE_DEC, NULL, 1<<8,
1320       NULL, HFILL }
1321     },
1322     { &hf_siii_at_dev_status_proc_command_change,
1323       { "Procedure Command Change", "siii.at.devstatus.proccmdchange",
1324       FT_UINT16, BASE_DEC, VALS(siii_at_dev_status_proc_command_change_text), 1<<5,
1325       NULL, HFILL }
1326     },
1327     { &hf_siii_at_dev_status_parameterization_level_active,
1328       { "Parameterization level active", "siii.at.devstatus.paralevelactive",
1329       FT_UINT16, BASE_DEC, NULL, 1<<4,
1330       NULL, HFILL }
1331     },
1332 
1333     { &hf_siii_mdt_svch_ctrl,
1334       {"SvcCtrl", "siii.mdt.svch.ctrl",
1335       FT_UINT16, BASE_HEX, NULL, 0,
1336       NULL, HFILL }
1337     },
1338     { &hf_siii_at_svch_stat,
1339       {"SvcStat", "siii.mdt.svch.stat",
1340       FT_UINT16, BASE_HEX, NULL, 0,
1341       NULL, HFILL }
1342     },
1343     { &hf_siii_mdt_svch_info,
1344       {"Svc Info", "siii.mdt.svch.info",
1345       FT_BYTES, BASE_NONE, NULL, 0,
1346       NULL, HFILL }
1347     },
1348     { &hf_siii_at_svch_info,
1349       {"Svc Info", "siii.at.svch.info",
1350       FT_BYTES, BASE_NONE, NULL, 0,
1351       NULL, HFILL }
1352     },
1353     { &hf_siii_mdt_svch_idn,
1354       {"IDN", "siii.mdt.svch.idn",
1355       FT_UINT32, BASE_HEX | BASE_EXT_STRING, &siii_mdt_idn_text_ext, 0,
1356       NULL, HFILL }
1357     },
1358     { &hf_siii_mdt_svch_dbe,
1359       { "Data block element", "siii.mdt.svch.dbe",
1360       FT_UINT16, BASE_DEC, VALS(siii_mdt_svch_dbe_text), 0x38,
1361       NULL, HFILL }
1362     },
1363     { &hf_siii_mdt_svch_eot,
1364       {"End of element transmission", "siii.mdt.svch.eot",
1365       FT_BOOLEAN, 16, TFS(&siii_mdt_svch_eot_text), 0x04,
1366       NULL, HFILL }
1367     },
1368     { &hf_siii_mdt_svch_rw,
1369       {"Read/Write", "siii.mdt.svch.rw",
1370       FT_BOOLEAN, 16, TFS(&siii_mdt_svch_rw_text), 0x02,
1371       NULL, HFILL }
1372     },
1373     { &hf_siii_mdt_svch_mhs,
1374       {"Master Handshake", "siii.mdt.svch.mhs",
1375       FT_UINT16, BASE_DEC, NULL, 0x01,
1376       NULL, HFILL }
1377     },
1378     { &hf_siii_at_svch_valid,
1379       { "SVC process", "siii.mdt.svch.proc",
1380       FT_BOOLEAN, 16, TFS(&tfs_valid_not_valid), 0x08,
1381       NULL, HFILL }
1382     },
1383     { &hf_siii_at_svch_error,
1384       {"SVC Error", "siii.mdt.svch.error",
1385       FT_BOOLEAN, 16, TFS(&siii_at_svch_error_text), 0x04,
1386       NULL, HFILL }
1387     },
1388     { &hf_siii_at_svch_busy,
1389       {"Busy", "siii.mdt.svch.busy",
1390       FT_BOOLEAN, 16, TFS(&siii_at_svch_busy_text), 0x02,
1391       NULL, HFILL }
1392     },
1393     { &hf_siii_at_svch_ahs,
1394       {"Handshake", "siii.at.svch.ahs",
1395       FT_UINT16, BASE_DEC, NULL, 0x01,
1396       NULL, HFILL }
1397     },
1398 #if 0
1399     { &hf_siii_svch_data_telofs_telno,
1400       {"Telegram Number", "siii.mdt.svch.data.telassign.telno",
1401       FT_UINT16, BASE_DEC, NULL, 0xF000,
1402       NULL, HFILL }
1403     },
1404 #endif
1405 #if 0
1406     { &hf_siii_svch_data_telofs_mdt_at,
1407       {"Telegram Type", "siii.mdt.svch.data.telassign.mdt_at",
1408       FT_UINT16, BASE_DEC, VALS(siii_svch_data_mdt_at_text), 0x0800,
1409       NULL, HFILL }
1410     },
1411 #endif
1412 #if 0
1413     { &hf_siii_svch_data_telofs_offset,
1414       {"Telegram Offset", "siii.mdt.svch.data.telassign.offset",
1415       FT_UINT16, BASE_DEC, NULL, 0x07FF,
1416       NULL, HFILL }
1417     },
1418 #endif
1419 #if 0
1420     { &hf_siii_svch_data_proccmd_proccmdexec,
1421       {"Procedure Command Execution", "siii.mdt.svch.data.proccmd.interrupt",
1422       FT_UINT16, BASE_DEC, VALS(siii_svch_data_proccmd_proccmdexec_text), 0x0002,
1423       NULL, HFILL }
1424     },
1425 #endif
1426 #if 0
1427     { &hf_siii_svch_data_proccmd_proccmd,
1428       {"Procedure Command", "siii.mdt.svch.data.proccmd.set",
1429       FT_UINT16, BASE_DEC, VALS(siii_svch_data_proccmd_proccmd_text), 0x0001,
1430       NULL, HFILL }
1431     },
1432 #endif
1433     { &hf_siii_mst_channel,
1434       { "Channel", "siii.channel",
1435         FT_UINT8, BASE_DEC, VALS(siii_mst_channel_text), 0x80,
1436         NULL, HFILL }
1437     },
1438     { &hf_siii_mst_type,
1439       { "Telegram Type" , "siii.type",
1440         FT_UINT8, BASE_DEC, VALS(siii_mst_type_text), 0x40,
1441         NULL, HFILL }
1442     },
1443     { &hf_siii_mst_cyclecntvalid,
1444       { "Cycle Count Valid", "siii.cyclecntvalid",
1445         FT_BOOLEAN, 8, TFS(&tfs_valid_invalid), 0x20,
1446         NULL, HFILL }
1447     },
1448     { &hf_siii_mst_telno,
1449       { "Telegram Number", "siii.telno",
1450         FT_UINT8, BASE_DEC, NULL, 0x0F,
1451         NULL, HFILL }
1452     },
1453     { &hf_siii_mst_phase,
1454       { "Phase", "siii.mst.phase",
1455         FT_UINT8, BASE_HEX, VALS(siii_mst_phase_text), 0x8F,    /* CHANGED: SB: new value is 0x8F for masking out phase */
1456         NULL, HFILL }
1457     },
1458     { &hf_siii_mst_cyclecnt,
1459       { "Cycle Cnt", "siii.mst.cyclecnt",
1460         FT_UINT8, BASE_DEC, NULL, 0x70,    /* CHANGED: SB: new value is 0x70 for masking out cycle cnt */
1461         NULL, HFILL }
1462     },
1463     { &hf_siii_mst_crc32,
1464       { "CRC32", "siii.mst.crc32",
1465         FT_UINT32, BASE_HEX, NULL, 0,
1466         NULL, HFILL }
1467     },
1468 
1469     { &hf_siii_mdt_hotplug_address,
1470       {"Sercos address", "siii.mdt.hp.sercosaddress",
1471         FT_UINT16, BASE_HEX, NULL, 0,
1472         NULL, HFILL }
1473     },
1474     { &hf_siii_mdt_hp_ctrl,
1475       {"HP control", "siii.mdt.hp.ctrl",
1476         FT_UINT16, BASE_HEX, NULL, 0,
1477         NULL, HFILL }
1478     },
1479     { &hf_siii_mdt_hp_info,
1480       {"HP info", "siii.mdt.hp.info",
1481         FT_BYTES, BASE_NONE, NULL, 0,
1482         NULL, HFILL }
1483     },
1484     { &hf_siii_at_hotplug_address,
1485       {"Sercos address", "siii.at.hp.sercosaddress",
1486         FT_UINT16, BASE_HEX, NULL, 0,
1487         NULL, HFILL }
1488     },
1489     { &hf_siii_at_hp_stat,
1490       {"HP status", "siii.mdt.hp.stat",
1491         FT_UINT16, BASE_HEX, NULL, 0,
1492         NULL, HFILL }
1493     },
1494     { &hf_siii_at_hp_info,
1495       {"HP info", "siii.at.hp.info",
1496         FT_BYTES, BASE_NONE, NULL, 0,
1497         NULL, HFILL }
1498     },
1499     { &hf_siii_mdt_hotplug_control_param,
1500       {"Parameter", "siii.mdt.hp.parameter",
1501         FT_UINT16, BASE_DEC | BASE_EXT_STRING, &siii_mdt_hotplug_control_functioncode_text_ext, 0xFF,
1502         NULL, HFILL }
1503     },
1504     { &hf_siii_mdt_hotplug_control_svc_switch,
1505       {"Switch to SVC", "siii.mdt.hp.switch",
1506         FT_UINT16, BASE_DEC, VALS(siii_mdt_hotplug_control_svc_switch_text), 0x100,
1507         NULL, HFILL }
1508     },
1509 
1510     { &hf_siii_at_hotplug_status_param,
1511       {"Parameter Received", "siii.at.hp.parameter",
1512         FT_UINT16, BASE_DEC, VALS(siii_mdt_hotplug_status_ackcode_text), 0xFF,
1513         NULL, HFILL }
1514     },
1515     { &hf_siii_at_hotplug_status_hp0_finished,
1516       {"HP/SVC", "siii.at.hp.hp0_finished",
1517         FT_UINT16, BASE_DEC, NULL, 0x100,
1518         NULL, HFILL }
1519     },
1520     { &hf_siii_at_hotplug_status_error,
1521       {"Error", "siii.at.hp.error",
1522         FT_UINT16, BASE_DEC, VALS(siii_at_hotplug_status_error_text), 0x200,
1523         NULL, HFILL }
1524     },
1525     { &hf_siii_service_channels,
1526       {"Service Channels", "siii.service_channels",
1527         FT_NONE, BASE_NONE, NULL, 0x0,
1528         NULL, HFILL }
1529     },
1530     { &hf_siii_device_controls,
1531       {"Device Controls", "siii.device_controls",
1532         FT_NONE, BASE_NONE, NULL, 0x0,
1533         NULL, HFILL }
1534     },
1535     { &hf_siii_device_status,
1536       {"Device Status", "siii.device_status",
1537         FT_NONE, BASE_NONE, NULL, 0x0,
1538         NULL, HFILL }
1539     },
1540     { &hf_siii_idn_code,
1541       {"IDN code", "siii.idn_code",
1542         FT_UINT32, BASE_CUSTOM, CF_FUNC(sercosiii_idn_code_format), 0x0,
1543         NULL, HFILL }
1544     },
1545     { &hf_siii_at_cp0_num_devices,
1546       {"Number of Devices", "siii.at.cp0.num_devices",
1547         FT_UINT16, BASE_DEC, NULL, 0x0,
1548         NULL, HFILL }
1549     },
1550     { &hf_siii_at_cp0_sercos_address,
1551       {"Sercos Address", "siii.at.cp0.sercos_address",
1552         FT_UINT16, BASE_DEC, NULL, 0x0,
1553         NULL, HFILL }
1554     },
1555   };
1556 
1557   /* Setup protocol subtree array */
1558   static gint *ett[] = {
1559     &ett_siii,
1560     &ett_siii_header,
1561 
1562     &ett_siii_mdt,
1563     &ett_siii_mdt_version,
1564     &ett_siii_mdt_svc,
1565     &ett_siii_mdt_devctrls,
1566     &ett_siii_mdt_svc_channel,
1567     &ett_siii_mdt_dev_control,
1568 
1569     &ett_siii_at,
1570     &ett_siii_at_svc,
1571     &ett_siii_at_sercos_address,
1572     &ett_siii_at_devstats,
1573     &ett_siii_at_svc_channel,
1574     &ett_siii_at_dev_status,
1575 
1576     &ett_siii_mdt_devctrl,
1577     &ett_siii_at_devstatus,
1578     &ett_siii_at_sercosaddress,
1579 
1580     &ett_siii_mdt_svcctrl,
1581     &ett_siii_mdt_svcinfo,
1582     &ett_siii_at_svcstat,
1583     &ett_siii_at_svcinfo,
1584     &ett_siii_mdt_svch_data_error_info,
1585     &ett_siii_mdt_svch_data,
1586 
1587     &ett_siii_mst,
1588     &ett_siii_mst_teltype,
1589     &ett_siii_mst_phase,
1590 
1591     &ett_siii_mdt_hp,
1592     &ett_siii_at_hp,
1593     &ett_siii_mdt_hp_ctrl,
1594     &ett_siii_mdt_hp_info,
1595     &ett_siii_at_hp_stat,
1596     &ett_siii_at_hp_info,
1597     &ett_siii_recognized_devices
1598   };
1599 
1600   static ei_register_info ei[] = {
1601     { &ei_siii_cp_unknown, { "siii.cp_unknown", PI_PROTOCOL, PI_WARN, "CP is unknown", EXPFILL }},
1602   };
1603 
1604   expert_module_t* expert_siii;
1605 
1606   /* Register the protocol name and description */
1607   proto_siii = proto_register_protocol("SERCOS III V1.1",
1608       "SERCOS III V1.1", "siii");
1609 
1610   register_dissector("sercosiii", dissect_siii, proto_siii);
1611 
1612   /* subdissector code */
1613   heur_subdissector_list = register_heur_dissector_list("sercosiii", proto_siii);
1614 
1615   /* Required function calls to register the header fields and subtrees used */
1616   proto_register_field_array(proto_siii, hf, array_length(hf));
1617   proto_register_subtree_array(ett, array_length(ett));
1618   expert_siii = expert_register_protocol(proto_siii);
1619   expert_register_field_array(expert_siii, ei, array_length(ei));
1620 }
1621 
1622 void
proto_reg_handoff_sercosiii(void)1623 proto_reg_handoff_sercosiii(void)
1624 {
1625   dissector_handle_t siii_handle;
1626 
1627   siii_handle = create_dissector_handle(dissect_siii, proto_siii);
1628   dissector_add_uint("ethertype", ETHERTYPE_SERCOS, siii_handle);
1629 }
1630 
1631 /*
1632  * Editor modelines
1633  *
1634  * Local Variables:
1635  * c-basic-offset: 2
1636  * tab-width: 8
1637  * indent-tabs-mode: nil
1638  * End:
1639  *
1640  * ex: set shiftwidth=2 tabstop=8 expandtab:
1641  * :indentSize=2:tabSize=8:noTabs=true:
1642  */
1643