2 * Routines for "Ethernet POWERLINK 2.0" dissection
3 * (Ethernet POWERLINK V2.0 Communication Profile Specification Draft Standard Version 1.2.0)
5 * Copyright (c) 2006: Zurich University of Applied Sciences Winterthur (ZHW)
6 * Institute of Embedded Systems (InES)
9 * - Dominic Bechaz <bdo[AT]zhwin.ch>
10 * - Damir Bursic <bum[AT]zhwin.ch>
11 * - David Buechi <bhd[AT]zhwin.ch>
13 * Copyright (c) 2007: SYS TEC electronic GmbH
14 * http://www.systec-electronic.com
15 * - Daniel Krueger <daniel.krueger[AT]systec-electronic.com>
17 * Copyright (c) 2013: B&R Industrieelektronik GmbH
18 * http://www.br-automation.com
20 * - Christoph Schlosser <christoph.schlosser[AT]br-automation.com>
21 * - Lukas Emersberger <lukas.emersberger[AT]br-automation.com>
22 * - Josef Baumgartner <josef.baumgartner[AT]br-automation.com>
23 * - Roland Knall <roland.knall[AT]br-automation.com>
24 * - Extended to be similair in handling as to B&R plugin
25 * - Multiple SOD Read/Write dissection
26 * - Include AInv message type
27 * - Straighten text formatting
28 * - Remove unnecessary if(tree) checks
30 * Copyright (c) 2017: Karlsruhe Institute of Technology (KIT)
31 * Institute for Anthropomatics and Robotics (IAR)
32 * Intelligent Process Control and Robotics (IPR)
33 * http://rob.ipr.kit.edu/
35 * - Ahmad Fatoum <ahmad[AT]a3f.at>
36 * - ObjectMappings now used for dissecting PDOs
37 * - XDD/EDS files can be read for name/type information
39 * Copyright (c) 2020: B&R Industrial Automation GmbH
40 * http://www.br-automation.com
42 * - Christian Krump <christian.krump[AT]br-automation.com>
43 * - extended decoding of ring redundancy flags in the SOA frame
44 * - put a boolean hotfield to all available EPL message types
45 * - modified timestamp format of errorcodelist entries
46 * - append summary info with additional flag information
47 * - usage of segment size during sdo (write by index) payload decoding process
48 * - set mapping-sections of sdo objects one level lower
49 * - dissect some additional (cable redundancy specific) flags
52 * Wireshark - Network traffic analyzer
53 * By Gerald Combs <gerald@wireshark.org>
54 * Copyright 1999 Gerald Combs
56 * SPDX-License-Identifier: GPL-2.0-or-later
61 #include "packet-epl.h"
63 #include <epan/conversation.h>
64 #include <epan/packet.h>
65 #include <epan/etypes.h>
66 #include <epan/prefs.h>
67 #include <epan/expert.h>
68 #include <epan/reassemble.h>
69 #include <epan/proto_data.h>
70 #include <epan/strutil.h>
73 #include <wsutil/strtoi.h>
74 #include <wsutil/file_util.h>
75 #include <wsutil/report_message.h>
76 #include <wsutil/wslog.h>
80 #define IF_LIBXML(x) x
85 void proto_register_epl(void);
86 void proto_reg_handoff_epl(void);
89 #define UDP_PORT_EPL 3819
92 /* Allow heuristic dissection and ASND manufacturer dissection */
93 static heur_dissector_list_t heur_epl_subdissector_list
;
94 static heur_dissector_list_t heur_epl_data_subdissector_list
;
95 static dissector_table_t epl_asnd_dissector_table
;
97 /* Container for tapping relevant data */
98 typedef struct _epl_info_t
{
99 unsigned char epl_mtyp
;
104 #define EPL_DYNAMIC_NODEID 0
105 #define EPL_MN_NODEID 240
106 #define EPL_DIAGNOSTIC_DEVICE_NODEID 253
107 #define EPL_TO_LEGACY_ETHERNET_ROUTER_NODEID 254
108 #define EPL_BROADCAST_NODEID 255
109 #define EPL_IS_CN_NODEID(nodeid) (EPL_DYNAMIC_NODEID < (nodeid) && (nodeid) < EPL_MN_NODEID)
111 static const value_string addr_str_vals
[] = {
112 {EPL_DYNAMIC_NODEID
, " (Dynamically assigned)" },
113 {EPL_MN_NODEID
, " (Managing Node)" },
114 {EPL_DIAGNOSTIC_DEVICE_NODEID
, " (Diagnostic Device)" },
115 {EPL_TO_LEGACY_ETHERNET_ROUTER_NODEID
, " (POWERLINK to legacy Ethernet Router)" },
116 {EPL_BROADCAST_NODEID
, " (broadcast)" },
120 static const value_string addr_str_abbr_vals
[] _U_
= {
121 {EPL_DYNAMIC_NODEID
, " (dyn.)" },
122 {EPL_MN_NODEID
, " (MN)" },
123 {EPL_DIAGNOSTIC_DEVICE_NODEID
, " (diag.)" },
124 {EPL_TO_LEGACY_ETHERNET_ROUTER_NODEID
, " (router)" },
125 {EPL_BROADCAST_NODEID
, " (bc)" },
129 static const char* addr_str_abbr_cn = " (CN)";
130 static const char* addr_str_abbr_res = " (res.)";
135 /* Offsets of fields within an EPL packet. */
136 #define EPL_MTYP_OFFSET 0 /* same offset for all message types*/
137 #define EPL_DEST_OFFSET 1 /* same offset for all message types*/
138 #define EPL_SRC_OFFSET 2 /* same offset for all message types*/
140 #define EPL_SOA_SVID_OFFSET 6
141 #define EPL_SOA_SVTG_OFFSET 7
142 #define EPL_SOA_EPLV_OFFSET 8
144 #define EPL_SOA_SYNC_OFFSET 10
145 #define EPL_SOA_PRFE_OFFSET 14
146 #define EPL_SOA_PRSE_OFFSET 18
147 #define EPL_SOA_MNDF_OFFSET 22
148 #define EPL_SOA_MNDS_OFFSET 26
149 #define EPL_SOA_PRTO_OFFSET 30
150 #define EPL_SOA_DEST_OFFSET 34
152 #define EPL_ASND_SVID_OFFSET 3
153 #define EPL_ASND_DATA_OFFSET 4
154 /* NMT Command DNA size */
155 #define EPL_SIZEOF_NMTCOMMAND_DNA 27
157 /* EPL message types */
159 #define EPL_PREQ 0x03
160 #define EPL_PRES 0x04
162 #define EPL_ASND 0x06
163 #define EPL_AMNI 0x07
164 #define EPL_AINV 0x0D
166 static const value_string mtyp_vals
[] = {
167 {EPL_SOC
, "Start of Cycle (SoC)" },
168 {EPL_PREQ
, "PollRequest (PReq)" },
169 {EPL_PRES
, "PollResponse (PRes)" },
170 {EPL_SOA
, "Start of Asynchronous (SoA)" },
171 {EPL_ASND
, "Asynchronous Send (ASnd)" },
172 {EPL_AINV
, "Asynchronous Invite (AInv)" },
173 {EPL_AMNI
, "ActiveManagingNodeIndication (AMNI)" },
178 #define EPL_SOC_MC_MASK 0x80
179 #define EPL_SOC_PS_MASK 0x40
180 #define EPL_SOC_AN_MASK 0x08
181 #define EPL_PDO_RD_MASK 0x01
182 #define EPL_PDO_EA_MASK 0x04
183 #define EPL_PDO_EN_MASK 0x10
184 #define EPL_PDO_RS_MASK 0x07
185 #define EPL_PDO_PR_MASK 0x38
186 #define EPL_PDO_SLS_MASK 0x40
187 #define EPL_PDO_FLS_MASK 0x80
188 #define EPL_SOA_EA_MASK 0x04
189 #define EPL_SOA_ER_MASK 0x02
190 #define EPL_ASND_EN_MASK 0x10
191 #define EPL_ASND_EC_MASK 0x08
192 #define EPL_ASND_RS_MASK 0x07
193 #define EPL_ASND_PR_MASK 0x38
194 #define EPL_ASND_SLS_MASK 0x40
195 #define EPL_ASND_FLS_MASK 0x80
197 /* RequestedServiceID s for EPL message type "SoA" */
198 #define EPL_SOA_NOSERVICE 0
199 #define EPL_SOA_IDENTREQUEST 1
200 #define EPL_SOA_STATUSREQUEST 2
201 #define EPL_SOA_NMTREQUESTINVITE 3
202 #define EPL_SOA_SYNCREQUEST 6
203 #define EPL_SOA_UNSPECIFIEDINVITE 255
205 #define EPL_SOA_SYNC_PRES_FIRST 0x01
206 #define EPL_SOA_SYNC_PRES_SECOND 0x02
207 #define EPL_SOA_SYNC_MND_FIRST 0x04
208 #define EPL_SOA_SYNC_MND_SECOND 0x08
209 #define EPL_SOA_SYNC_PRES_TIMEOUT 0x10
210 #define EPL_SOA_SYNC_MAC_VALID 0x20
211 #define EPL_SOA_SYNC_PRES_RESET 0x40
212 #define EPL_SOA_SYNC_PRES_SET 0x80
214 static const range_string soa_svid_vals
[] = {
215 {EPL_SOA_NOSERVICE
, EPL_SOA_NOSERVICE
, "NoService"},
216 {EPL_SOA_IDENTREQUEST
, EPL_SOA_IDENTREQUEST
, "IdentRequest"},
217 {EPL_SOA_STATUSREQUEST
, EPL_SOA_STATUSREQUEST
, "StatusRequest"},
218 {EPL_SOA_NMTREQUESTINVITE
, EPL_SOA_NMTREQUESTINVITE
, "NMTRequestInvite"},
219 {0x04, 0x05, "Reserved"},
220 {EPL_SOA_SYNCREQUEST
, EPL_SOA_SYNCREQUEST
, "SyncRequest"},
221 {0x07, 0x9F, "Reserved"},
222 {0xA0, 0xFE, "Manufacturer Specific"},
223 {EPL_SOA_UNSPECIFIEDINVITE
, EPL_SOA_UNSPECIFIEDINVITE
, "UnspecifiedInvite"},
227 /* ServiceID values for EPL message type "ASnd" */
228 #define EPL_ASND_IDENTRESPONSE 1
229 #define EPL_ASND_STATUSRESPONSE 2
230 #define EPL_ASND_NMTREQUEST 3
231 #define EPL_ASND_NMTCOMMAND 4
232 #define EPL_ASND_SDO 5
233 #define EPL_ASND_SYNCRESPONSE 6
235 #define EPL_ASND_SYNCRESPONSE_FST_VALID 0x01
236 #define EPL_ASND_SYNCRESPONSE_SEC_VALID 0x02
237 #define EPL_ASND_SYNCRESPONSE_MODE 0x80
239 static const range_string soa_svid_id_vals
[] = {
240 {EPL_SOA_NOSERVICE
, EPL_SOA_NOSERVICE
, "NO_SERVICE"},
241 {EPL_SOA_IDENTREQUEST
, EPL_SOA_IDENTREQUEST
, "IDENT_REQUEST"},
242 {EPL_SOA_STATUSREQUEST
, EPL_SOA_STATUSREQUEST
, "STATUS_REQUEST"},
243 {EPL_SOA_NMTREQUESTINVITE
, EPL_SOA_NMTREQUESTINVITE
, "NMT_REQUEST_INV"},
244 {0x04, 0x05, "RESERVED"},
245 {EPL_SOA_SYNCREQUEST
, EPL_SOA_SYNCREQUEST
, "SYNC_REQUEST"},
246 {0x07, 0x9F, "RESERVED"},
247 {0xA0, 0xFE, "MANUFACTURER SPECIFIC"},
248 {EPL_SOA_UNSPECIFIEDINVITE
, EPL_SOA_UNSPECIFIEDINVITE
, "UNSPEC_INVITE"},
252 static const range_string asnd_svid_vals
[] = {
254 {EPL_ASND_IDENTRESPONSE
, EPL_ASND_IDENTRESPONSE
, "IdentResponse"},
255 {EPL_ASND_STATUSRESPONSE
, EPL_ASND_STATUSRESPONSE
, "StatusResponse"},
256 {EPL_ASND_NMTREQUEST
, EPL_ASND_NMTREQUEST
, "NMTRequest"},
257 {EPL_ASND_NMTCOMMAND
, EPL_ASND_NMTCOMMAND
, "NMTCommand"},
258 {EPL_ASND_SDO
, EPL_ASND_SDO
, "SDO"},
259 {EPL_ASND_SYNCRESPONSE
, EPL_ASND_SYNCRESPONSE
, "SyncResponse"},
260 {0x07, 0x9F, "Reserved"},
261 {0xA0, 0xFE, "Manufacturer Specific"},
262 {0xFF, 0xFF, "Reserved"},
266 static const range_string asnd_svid_id_vals
[] = {
268 {EPL_ASND_IDENTRESPONSE
, EPL_ASND_IDENTRESPONSE
, "IDENT_RESPONSE"},
269 {EPL_ASND_STATUSRESPONSE
, EPL_ASND_STATUSRESPONSE
, "STATUS_RESPONSE"},
270 {EPL_ASND_NMTREQUEST
, EPL_ASND_NMTREQUEST
, "NMT_REQUEST"},
271 {EPL_ASND_NMTCOMMAND
, EPL_ASND_NMTCOMMAND
, "NMT_COMMAND"},
272 {EPL_ASND_SDO
, EPL_ASND_SDO
, "SDO"},
273 {EPL_ASND_SYNCRESPONSE
, EPL_ASND_SYNCRESPONSE
, "SYNC_RESPONSE"},
274 {0x07, 0x9F, "RESERVED"},
275 {0xA0, 0xFE, "MANUFACTURER SPECIFIC"},
276 {0xFF, 0xFF, "RESERVED"},
280 /* NMTCommand values for EPL message type "ASnd" */
281 #define EPL_ASND_NMTCOMMAND_NMTSTARTNODE 0x21
282 #define EPL_ASND_NMTCOMMAND_NMTSTOPNODE 0x22
283 #define EPL_ASND_NMTCOMMAND_NMTENTERPREOPERATIONAL2 0x23
284 #define EPL_ASND_NMTCOMMAND_NMTENABLEREADYTOOPERATE 0x24
285 #define EPL_ASND_NMTCOMMAND_NMTRESETNODE 0x28
286 #define EPL_ASND_NMTCOMMAND_NMTRESETCOMMUNICATION 0x29
287 #define EPL_ASND_NMTCOMMAND_NMTRESETCONFIGURATION 0x2A
288 #define EPL_ASND_NMTCOMMAND_NMTSWRESET 0x2B
289 #define EPL_ASND_NMTCOMMAND_NMTDNA 0x2D
291 #define EPL_ASND_NMTCOMMAND_NMTSTARTNODEEX 0x41
292 #define EPL_ASND_NMTCOMMAND_NMTSTOPNODEEX 0x42
293 #define EPL_ASND_NMTCOMMAND_NMTENTERPREOPERATIONAL2EX 0x43
294 #define EPL_ASND_NMTCOMMAND_NMTENABLEREADYTOOPERATEEX 0x44
295 #define EPL_ASND_NMTCOMMAND_NMTRESETNODEEX 0x48
296 #define EPL_ASND_NMTCOMMAND_NMTRESETCOMMUNICATIONEX 0x49
297 #define EPL_ASND_NMTCOMMAND_NMTRESETCONFIGURATIONEX 0x4A
298 #define EPL_ASND_NMTCOMMAND_NMTSWRESETEX 0x4B
300 #define EPL_ASND_NMTCOMMAND_NMTNETHOSTNAMESET 0x62
301 #define EPL_ASND_NMTCOMMAND_NMTFLUSHARPENTRY 0x63
302 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHCONFIGUREDNODES 0x80
303 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHACTIVENODES 0x90
304 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHPREOPERATIONAL1 0x91
305 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHPREOPERATIONAL2 0x92
306 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHREADYTOOPERATE 0x93
307 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHOPERATIONAL 0x94
308 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHSTOPPED 0x95
309 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHEMERGENCYNEW 0xA0
310 #define EPL_ASND_NMTCOMMAND_NMTPUBLISHTIME 0XB0
311 #define EPL_ASND_NMTCOMMAND_NMTINVALIDSERVICE 0xFF
313 static const value_string asnd_cid_vals
[] = {
314 /* "special" values to cover all possibilities of CommandID in NMTRequests */
315 {EPL_ASND_IDENTRESPONSE
, "IdentResponse" },
316 {EPL_ASND_STATUSRESPONSE
, "StatusResponse" },
318 {EPL_ASND_NMTCOMMAND_NMTSTARTNODE
, "NMTStartNode" },
319 {EPL_ASND_NMTCOMMAND_NMTSTOPNODE
, "NMTStopNode" },
320 {EPL_ASND_NMTCOMMAND_NMTENTERPREOPERATIONAL2
, "NMTEnterPreOperational2" },
321 {EPL_ASND_NMTCOMMAND_NMTENABLEREADYTOOPERATE
, "NMTEnableReadyToOperate" },
322 {EPL_ASND_NMTCOMMAND_NMTRESETNODE
, "NMTResetNode" },
323 {EPL_ASND_NMTCOMMAND_NMTRESETCOMMUNICATION
, "NMTResetCommunication" },
324 {EPL_ASND_NMTCOMMAND_NMTRESETCONFIGURATION
, "NMTResetConfiguration" },
325 {EPL_ASND_NMTCOMMAND_NMTSWRESET
, "NMTSwReset" },
326 {EPL_ASND_NMTCOMMAND_NMTDNA
, "NMTDNA" },
327 {EPL_ASND_NMTCOMMAND_NMTSTARTNODEEX
, "NMTStartNodeEx" },
328 {EPL_ASND_NMTCOMMAND_NMTSTOPNODEEX
, "NMTStopNodeEx" },
329 {EPL_ASND_NMTCOMMAND_NMTENTERPREOPERATIONAL2EX
, "NMTEnterPreOperational2Ex" },
330 {EPL_ASND_NMTCOMMAND_NMTENABLEREADYTOOPERATEEX
, "NMTEnableReadyToOperateEx" },
331 {EPL_ASND_NMTCOMMAND_NMTRESETNODEEX
, "NMTResetNodeEx" },
332 {EPL_ASND_NMTCOMMAND_NMTRESETCOMMUNICATIONEX
, "NMTCommunicationEx" },
333 {EPL_ASND_NMTCOMMAND_NMTRESETCONFIGURATIONEX
, "NMTResetConfigurationEx" },
334 {EPL_ASND_NMTCOMMAND_NMTSWRESETEX
, "NMTSwResetEx" },
335 {EPL_ASND_NMTCOMMAND_NMTNETHOSTNAMESET
, "NMTNetHostNameSet" },
336 {EPL_ASND_NMTCOMMAND_NMTFLUSHARPENTRY
, "NMTFlushArpEntry" },
337 {EPL_ASND_NMTCOMMAND_NMTPUBLISHCONFIGUREDNODES
, "NMTPublishConfiguredNodes" },
338 {EPL_ASND_NMTCOMMAND_NMTPUBLISHACTIVENODES
, "NMTPublishActiveNodes" },
339 {EPL_ASND_NMTCOMMAND_NMTPUBLISHPREOPERATIONAL1
, "NMTPublishPreOperational1" },
340 {EPL_ASND_NMTCOMMAND_NMTPUBLISHPREOPERATIONAL2
, "NMTPublishPreOperational2" },
341 {EPL_ASND_NMTCOMMAND_NMTPUBLISHREADYTOOPERATE
, "NMTPublishReadyToOperate" },
342 {EPL_ASND_NMTCOMMAND_NMTPUBLISHOPERATIONAL
, "NMTPublishOperational" },
343 {EPL_ASND_NMTCOMMAND_NMTPUBLISHSTOPPED
, "NMTPublishStopped" },
344 {EPL_ASND_NMTCOMMAND_NMTPUBLISHEMERGENCYNEW
, "NMTPublishEmergencyNew" },
345 {EPL_ASND_NMTCOMMAND_NMTPUBLISHTIME
, "NMTPublishTime" },
346 {EPL_ASND_NMTCOMMAND_NMTINVALIDSERVICE
, "NMTInvalidService" },
349 static value_string_ext asnd_cid_vals_ext
= VALUE_STRING_EXT_INIT(asnd_cid_vals
);
351 /* Maximal Sequence */
352 #define EPL_MAX_SEQUENCE 0x40
353 #define EPL_MAX_ADDRESSES 0xF1
354 /* SCON and RCON values*/
355 #define EPL_NO_CONNECTION 0x00
356 #define EPL_INITIALIZATION 0x01
357 #define EPL_VALID 0x02
358 #define EPL_ACKREQ 0x03
359 #define EPL_RETRANSMISSION 0x03
360 /* MAX Frame offset */
361 #define EPL_MAX_FRAME_OFFSET 0x64
364 #define E_NO_ERROR 0x0000
365 #define E_NMT_NO_IDENT_RES 0xF001
366 #define E_NMT_NO_STATUS_RES 0xF002
367 #define E_DLL_BAD_PHYS_MODE 0x8161
368 #define E_DLL_COLLISION 0x8162
369 #define E_DLL_COLLISION_TH 0x8163
370 #define E_DLL_CRC_TH 0x8164
371 #define E_DLL_LOSS_OF_LINK 0x8165
372 #define E_DLL_MAC_BUFFER 0x8166
373 #define E_DLL_ADDRESS_CONFLICT 0x8201
374 #define E_DLL_MULTIPLE_MN 0x8202
375 #define E_PDO_SHORT_RX 0x8210
376 #define E_PDO_MAP_VERS 0x8211
377 #define E_NMT_ASND_MTU_DIF 0x8212
378 #define E_NMT_ASND_MTU_LIM 0x8213
379 #define E_NMT_ASND_TX_LIM 0x8214
380 #define E_NMT_CYCLE_LEN 0x8231
381 #define E_DLL_CYCLE_EXCEED 0x8232
382 #define E_DLL_CYCLE_EXCEED_TH 0x8233
383 #define E_NMT_IDLE_LIM 0x8234
384 #define E_DLL_JITTER_TH 0x8235
385 #define E_DLL_LATE_PRES_TH 0x8236
386 #define E_NMT_PREQ_CN 0x8237
387 #define E_NMT_PREQ_LIM 0x8238
388 #define E_NMT_PRES_CN 0x8239
389 #define E_NMT_PRES_RX_LIM 0x823A
390 #define E_NMT_PRES_TX_LIM 0x823B
391 #define E_DLL_INVALID_FORMAT 0x8241
392 #define E_DLL_LOSS_PREQ_TH 0x8242
393 #define E_DLL_LOSS_PRES_TH 0x8243
394 #define E_DLL_LOSS_SOA_TH 0x8244
395 #define E_DLL_LOSS_SOC_TH 0x8245
396 #define E_NMT_BA1 0x8410
397 #define E_NMT_BA1_NO_MN_SUPPORT 0x8411
398 #define E_NMT_BPO1 0x8420
399 #define E_NMT_BPO1_GET_IDENT 0x8421
400 #define E_NMT_BPO1_DEVICE_TYPE 0x8422
401 #define E_NMT_BPO1_VENDOR_ID 0x8423
402 #define E_NMT_BPO1_PRODUCT_CODE 0x8424
403 #define E_NMT_BPO1_REVISION_NO 0x8425
404 #define E_NMT_BPO1_SERIAL_NO 0x8426
405 #define E_NMT_BPO1_CF_VERIFY 0x8428
406 #define E_NMT_BPO2 0x8430
407 #define E_NMT_BRO 0x8440
408 #define E_NMT_WRONG_STATE 0x8480
410 static const value_string errorcode_vals
[] = {
411 { E_NO_ERROR
, "E_NO_ERROR" },
412 { E_DLL_BAD_PHYS_MODE
, "E_DLL_BAD_PHYS_MODE" },
413 { E_DLL_COLLISION
, "E_DLL_COLLISION" },
414 { E_DLL_COLLISION_TH
, "E_DLL_COLLISION_TH" },
415 { E_DLL_CRC_TH
, "E_DLL_CRC_TH" },
416 { E_DLL_LOSS_OF_LINK
, "E_DLL_LOSS_OF_LINK" },
417 { E_DLL_MAC_BUFFER
, "E_DLL_MAC_BUFFER" },
418 { E_DLL_ADDRESS_CONFLICT
, "E_DLL_ADDRESS_CONFLICT" },
419 { E_DLL_MULTIPLE_MN
, "E_DLL_MULTIPLE_MN" },
420 { E_PDO_SHORT_RX
, "E_PDO_SHORT_RX" },
421 { E_PDO_MAP_VERS
, "E_PDO_MAP_VERS" },
422 { E_NMT_ASND_MTU_DIF
, "E_NMT_ASND_MTU_DIF" },
423 { E_NMT_ASND_MTU_LIM
, "E_NMT_ASND_MTU_LIM" },
424 { E_NMT_ASND_TX_LIM
, "E_NMT_ASND_TX_LIM" },
425 { E_NMT_CYCLE_LEN
, "E_NMT_CYCLE_LEN" },
426 { E_DLL_CYCLE_EXCEED
, "E_DLL_CYCLE_EXCEED" },
427 { E_DLL_CYCLE_EXCEED_TH
, "E_DLL_CYCLE_EXCEED_TH" },
428 { E_NMT_IDLE_LIM
, "E_NMT_IDLE_LIM" },
429 { E_DLL_JITTER_TH
, "E_DLL_JITTER_TH" },
430 { E_DLL_LATE_PRES_TH
, "E_DLL_LATE_PRES_TH" },
431 { E_NMT_PREQ_CN
, "E_NMT_PREQ_CN" },
432 { E_NMT_PREQ_LIM
, "E_NMT_PREQ_LIM" },
433 { E_NMT_PRES_CN
, "E_NMT_PRES_CN" },
434 { E_NMT_PRES_RX_LIM
, "E_NMT_PRES_RX_LIM" },
435 { E_NMT_PRES_TX_LIM
, "E_NMT_PRES_TX_LIM" },
436 { E_DLL_INVALID_FORMAT
, "E_DLL_INVALID_FORMAT" },
437 { E_DLL_LOSS_PREQ_TH
, "E_DLL_LOSS_PREQ_TH" },
438 { E_DLL_LOSS_PRES_TH
, "E_DLL_LOSS_PRES_TH" },
439 { E_DLL_LOSS_SOA_TH
, "E_DLL_LOSS_SOA_TH" },
440 { E_DLL_LOSS_SOC_TH
, "E_DLL_LOSS_SOC_TH" },
441 { E_NMT_BA1
, "E_NMT_BA1" },
442 { E_NMT_BA1_NO_MN_SUPPORT
, "E_NMT_BA1_NO_MN_SUPPORT" },
443 { E_NMT_BPO1
, "E_NMT_BPO1" },
444 { E_NMT_BPO1_GET_IDENT
, "E_NMT_BPO1_GET_IDENT" },
445 { E_NMT_BPO1_DEVICE_TYPE
, "E_NMT_BPO1_DEVICE_TYPE" },
446 { E_NMT_BPO1_VENDOR_ID
, "E_NMT_BPO1_VENDOR_ID" },
447 { E_NMT_BPO1_PRODUCT_CODE
, "E_NMT_BPO1_PRODUCT_CODE" },
448 { E_NMT_BPO1_REVISION_NO
, "E_NMT_BPO1_REVISION_NO" },
449 { E_NMT_BPO1_SERIAL_NO
, "E_NMT_BPO1_SERIAL_NO" },
450 { E_NMT_BPO1_CF_VERIFY
, "E_NMT_BPO1_CF_VERIFY" },
451 { E_NMT_BPO2
, "E_NMT_BPO2" },
452 { E_NMT_BRO
, "E_NMT_BRO" },
453 { E_NMT_WRONG_STATE
, "E_NMT_WRONG_STATE" },
454 { E_NMT_NO_IDENT_RES
, "E_NMT_NO_IDENT_RES" },
455 { E_NMT_NO_STATUS_RES
, "E_NMT_NO_STATUS_RES" },
459 static value_string_ext errorcode_vals_ext
= VALUE_STRING_EXT_INIT(errorcode_vals
);
461 /* duplication table key */
469 /* duplication table value */
475 static uint32_t count
;
477 typedef struct _epl_sdo_reassembly
479 uint32_t frame
[EPL_MAX_SEQUENCE
][EPL_MAX_SEQUENCE
];
480 } epl_sdo_reassembly
;
482 static struct _epl_segmentation
{
489 static epl_sdo_reassembly epl_asnd_sdo_reassembly_write
;
490 static epl_sdo_reassembly epl_asnd_sdo_reassembly_read
;
491 static bool first_read
= true;
492 static bool first_write
= true;
494 /* Priority values for EPL message type "ASnd", "", "", field PR */
495 #define EPL_PR_GENERICREQUEST 0x03
496 #define EPL_PR_NMTREQUEST 0x07
498 static const value_string epl_pr_vals
[] = {
501 {2, "below generic"},
502 {EPL_PR_GENERICREQUEST
, "GenericRequest"},
503 {4, "above generic"},
505 {6, "below NMTRequest"},
506 {EPL_PR_NMTREQUEST
, "NMTRequest"},
510 /* NMT State values (for CN)*/
511 #define EPL_NMT_GS_OFF 0x00
512 #define EPL_NMT_GS_INITIALIZING 0x19
513 #define EPL_NMT_GS_RESET_APPLICATION 0x29
514 #define EPL_NMT_GS_RESET_COMMUNICATION 0x39
515 #define EPL_NMT_CS_NOT_ACTIVE 0x1C
516 #define EPL_NMT_CS_PRE_OPERATIONAL_1 0x1D
517 #define EPL_NMT_CS_PRE_OPERATIONAL_2 0x5D
518 #define EPL_NMT_CS_READY_TO_OPERATE 0x6D
519 #define EPL_NMT_CS_OPERATIONAL 0xFD
520 #define EPL_NMT_CS_STOPPED 0x4D
521 #define EPL_NMT_CS_BASIC_ETHERNET 0x1E
523 static const value_string epl_nmt_cs_vals
[] = {
524 {EPL_NMT_GS_OFF
, "NMT_GS_OFF" },
525 {EPL_NMT_GS_INITIALIZING
, "NMT_GS_INITIALIZING" },
526 {EPL_NMT_GS_RESET_APPLICATION
, "NMT_GS_RESET_APPLICATION" },
527 {EPL_NMT_GS_RESET_COMMUNICATION
, "NMT_GS_RESET_COMMUNICATION"},
528 {EPL_NMT_CS_NOT_ACTIVE
, "NMT_CS_NOT_ACTIVE" },
529 {EPL_NMT_CS_PRE_OPERATIONAL_1
, "NMT_CS_PRE_OPERATIONAL_1" },
530 {EPL_NMT_CS_PRE_OPERATIONAL_2
, "NMT_CS_PRE_OPERATIONAL_2" },
531 {EPL_NMT_CS_READY_TO_OPERATE
, "NMT_CS_READY_TO_OPERATE" },
532 {EPL_NMT_CS_OPERATIONAL
, "NMT_CS_OPERATIONAL" },
533 {EPL_NMT_CS_STOPPED
, "NMT_CS_STOPPED" },
534 {EPL_NMT_CS_BASIC_ETHERNET
, "NMT_CS_BASIC_ETHERNET" },
538 /* NMT State values (for MN)*/
539 #define EPL_NMT_GS_OFF 0x00
540 #define EPL_NMT_GS_INITIALIZING 0x19
541 #define EPL_NMT_GS_RESET_APPLICATION 0x29
542 #define EPL_NMT_GS_RESET_COMMUNICATION 0x39
543 #define EPL_NMT_MS_NOT_ACTIVE 0x1C
544 #define EPL_NMT_MS_PRE_OPERATIONAL_1 0x1D
545 #define EPL_NMT_MS_PRE_OPERATIONAL_2 0x5D
546 #define EPL_NMT_MS_READY_TO_OPERATE 0x6D
547 #define EPL_NMT_MS_OPERATIONAL 0xFD
548 #define EPL_NMT_MS_BASIC_ETHERNET 0x1E
550 static const value_string epl_nmt_ms_vals
[] = {
551 {EPL_NMT_GS_OFF
, "NMT_GS_OFF" },
552 {EPL_NMT_GS_INITIALIZING
, "NMT_GS_INITIALIZING" },
553 {EPL_NMT_GS_RESET_APPLICATION
, "NMT_GS_RESET_APPLICATION" },
554 {EPL_NMT_GS_RESET_COMMUNICATION
, "NMT_GS_RESET_COMMUNICATION"},
555 {EPL_NMT_MS_NOT_ACTIVE
, "NMT_MS_NOT_ACTIVE" },
556 {EPL_NMT_MS_PRE_OPERATIONAL_1
, "NMT_MS_PRE_OPERATIONAL_1" },
557 {EPL_NMT_MS_PRE_OPERATIONAL_2
, "NMT_MS_PRE_OPERATIONAL_2" },
558 {EPL_NMT_MS_READY_TO_OPERATE
, "NMT_MS_READY_TO_OPERATE" },
559 {EPL_NMT_MS_OPERATIONAL
, "NMT_MS_OPERATIONAL" },
560 {EPL_NMT_MS_BASIC_ETHERNET
, "NMT_MS_BASIC_ETHERNET" },
564 /* EPL Device Profiles according to CANopen */
565 #define EPL_PROFILE_NO 0
566 #define EPL_PROFILE_GENERIC_IO 401
567 #define EPL_PROFILE_DRIVE 402
568 #define EPL_PROFILE_HMI 403
569 #define EPL_PROFILE_MEASURING 404
570 #define EPL_PROFILE_PLC 405
571 #define EPL_PROFILE_ENCODER 406
573 static const value_string epl_device_profiles
[] = {
574 {EPL_PROFILE_NO
, "No Standard Device"},
575 {EPL_PROFILE_GENERIC_IO
, "Generic I/O module"},
576 {EPL_PROFILE_DRIVE
, "Drive and motion control"},
577 {EPL_PROFILE_HMI
, "Human Machine Interface"},
578 {EPL_PROFILE_MEASURING
, "Measuring device"},
579 {EPL_PROFILE_PLC
, "IEC 61131-3 PLC"},
580 {EPL_PROFILE_ENCODER
, "Encoder"},
584 /* EPL Device Profiles loading */
585 /* User Access Table Checkers */
586 static bool epl_profile_uat_fld_fileopen_check_cb(void *, const char *, unsigned, const void *, const void *, char **);
587 static bool epl_uat_fld_cn_check_cb(void *, const char *, unsigned, const void *, const void *, char **);
588 static bool epl_uat_fld_uint16dec_check_cb(void *, const char *, unsigned, const void *, const void *, char **);
589 static bool epl_uat_fld_uint32hex_check_cb(void *, const char *, unsigned, const void *, const void *, char **);
591 /* DeviceType:Path User Access Table */
592 struct device_profile_uat_assoc
{
595 unsigned device_type
;
597 unsigned product_code
;
600 static uat_t
*device_profile_uat
;
601 static struct device_profile_uat_assoc
*device_profile_list_uats
;
602 static unsigned ndevice_profile_uat
;
604 static void *device_profile_uat_copy_cb(void *, const void *, size_t);
605 static void device_profile_uat_free_cb(void *);
606 static bool device_profile_uat_update_record(void *, char **);
607 static void device_profile_parse_uat(void);
609 UAT_DEC_CB_DEF(device_profile_list_uats
, device_type
, struct device_profile_uat_assoc
)
610 UAT_HEX_CB_DEF(device_profile_list_uats
, vendor_id
, struct device_profile_uat_assoc
)
611 UAT_HEX_CB_DEF(device_profile_list_uats
, product_code
, struct device_profile_uat_assoc
)
612 UAT_FILENAME_CB_DEF(device_profile_list_uats
, path
, struct device_profile_uat_assoc
)
614 static uat_field_t device_profile_list_uats_flds
[] = {
615 UAT_FLD_CSTRING_OTHER(device_profile_list_uats
, device_type
, "DeviceType", epl_uat_fld_uint16dec_check_cb
, "e.g. 401"),
616 UAT_FLD_CSTRING_OTHER(device_profile_list_uats
, vendor_id
, "VendorId", epl_uat_fld_uint32hex_check_cb
, "e.g. DEADBEEF"),
617 UAT_FLD_CSTRING_OTHER(device_profile_list_uats
, product_code
, "ProductCode", epl_uat_fld_uint32hex_check_cb
, "e.g. 8BADFOOD"),
619 UAT_FLD_FILENAME_OTHER(device_profile_list_uats
, path
, "Profile Path", epl_profile_uat_fld_fileopen_check_cb
, "Path to the EDS" IF_LIBXML("/XDD/XDC")),
624 /* NodeID:Path User Access Table */
625 struct nodeid_profile_uat_assoc
{
638 static uat_t
*nodeid_profile_uat
;
639 static struct nodeid_profile_uat_assoc
*nodeid_profile_list_uats
;
640 static unsigned nnodeid_profile_uat
;
643 static void nodeid_profile_list_uats_nodeid_set_cb(void *, const char *, unsigned, const void*, const void*);
644 static void nodeid_profile_list_uats_nodeid_tostr_cb(void *, char **, unsigned *, const void*, const void*);
645 static void *nodeid_profile_uat_copy_cb(void *, const void *, size_t);
646 static void nodeid_profile_uat_free_cb(void *);
647 static bool nodeid_profile_uat_update_record(void *, char **);
648 static void nodeid_profile_parse_uat(void);
650 UAT_FILENAME_CB_DEF(nodeid_profile_list_uats
, path
, struct nodeid_profile_uat_assoc
)
652 static uat_field_t nodeid_profile_list_uats_flds
[] = {
653 UAT_FLD_CSTRING_OTHER(nodeid_profile_list_uats
, nodeid
, "Node ID", epl_uat_fld_cn_check_cb
, "e.g. 1 or 00-00-5E-00-53-00"),
655 UAT_FLD_FILENAME_OTHER(nodeid_profile_list_uats
, path
, "Profile Path", epl_profile_uat_fld_fileopen_check_cb
, "Path to the EDS" IF_LIBXML("/XDD/XDC")),
662 /* SDO SequenceLayer */
663 #define EPL_ASND_SDO_SEQ_RECEIVE_SEQUENCE_NUMBER_OFFSET 4
664 #define EPL_ASND_SDO_SEQ_RECEIVE_CON_OFFSET 4
666 #define EPL_ASND_SDO_SEQ_SEND_SEQUENCE_NUMBER_OFFSET 5
667 #define EPL_ASND_SDO_SEQ_SEND_CON_OFFSET 5
669 #define EPL_ASND_SDO_SEQ_RECEIVE_CON_NO_CONNECTION 0x00
670 #define EPL_ASND_SDO_SEQ_RECEIVE_CON_INITIALIZATION 0x01
671 #define EPL_ASND_SDO_SEQ_RECEIVE_CON_CONNECTION_VALID 0x02
672 #define EPL_ASND_SDO_SEQ_RECEIVE_CON_ERROR_RESPONSE 0x03
673 #define EPL_ASND_SDO_SEQ_CON_MASK 0x03
674 #define EPL_ASND_SDO_SEQ_MASK 0x02
676 static const value_string epl_sdo_receive_con_vals
[] = {
677 {EPL_ASND_SDO_SEQ_RECEIVE_CON_NO_CONNECTION
, "No connection" },
678 {EPL_ASND_SDO_SEQ_RECEIVE_CON_INITIALIZATION
, "Initialization" },
679 {EPL_ASND_SDO_SEQ_RECEIVE_CON_CONNECTION_VALID
, "Connection valid" },
680 {EPL_ASND_SDO_SEQ_RECEIVE_CON_ERROR_RESPONSE
, "Error Response (retransmission request)"},
684 #define EPL_ASND_SDO_SEQ_SEND_CON_NO_CONNECTION 0x00
685 #define EPL_ASND_SDO_SEQ_SEND_CON_INITIALIZATION 0x01
686 #define EPL_ASND_SDO_SEQ_SEND_CON_CONNECTION_VALID 0x02
687 #define EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ 0x03
689 static const value_string epl_sdo_init_abbr_vals
[] = {
690 {EPL_ASND_SDO_SEQ_RECEIVE_CON_NO_CONNECTION
, "n" },
691 {EPL_ASND_SDO_SEQ_RECEIVE_CON_INITIALIZATION
, "i" },
692 {EPL_ASND_SDO_SEQ_RECEIVE_CON_CONNECTION_VALID
, "c" },
693 {EPL_ASND_SDO_SEQ_RECEIVE_CON_ERROR_RESPONSE
, "e" },
697 static const value_string epl_sdo_send_con_vals
[] = {
698 {EPL_ASND_SDO_SEQ_SEND_CON_NO_CONNECTION
, "No connection" },
699 {EPL_ASND_SDO_SEQ_SEND_CON_INITIALIZATION
, "Initialization" },
700 {EPL_ASND_SDO_SEQ_SEND_CON_CONNECTION_VALID
, "Connection valid" },
701 {EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ
, "Connection valid with acknowledge request" },
705 #define EPL_SDO_INIT_REQUEST ((EPL_NO_CONNECTION << 8) | EPL_INITIALIZATION)
706 #define EPL_SDO_INIT_ACK ((EPL_INITIALIZATION << 8) | EPL_INITIALIZATION)
707 #define EPL_SDO_INIT_RESPONSE ((EPL_INITIALIZATION << 8) | EPL_VALID)
708 #define EPL_SDO_VALID ((EPL_VALID << 8) | EPL_VALID)
709 #define EPL_SDO_RETRANSMISSION ((EPL_RETRANSMISSION << 8) | EPL_VALID)
710 #define EPL_SDO_ACKREQ ((EPL_VALID << 8) | EPL_ACKREQ)
711 #define EPL_SDO_CLOSE ((EPL_NO_CONNECTION << 8) | EPL_NO_CONNECTION)
713 static const value_string epl_sdo_init_con_vals
[] = {
714 {EPL_SDO_INIT_REQUEST
, "InitReq" },
715 {EPL_SDO_INIT_ACK
, "InitAck" },
716 {EPL_SDO_INIT_RESPONSE
, "InitResp" },
717 {EPL_SDO_VALID
, "Valid" },
718 {EPL_SDO_RETRANSMISSION
, "Retrans" },
719 {EPL_SDO_ACKREQ
, "AckReq" },
720 {EPL_SDO_CLOSE
, "Close" },
725 /* SDO Command Layer Protocol */
726 #define EPL_ASND_SDO_CMD_ABORT_FILTER 0x40
727 #define EPL_ASND_SDO_CMD_SEGMENTATION_FILTER 0x30
728 #define EPL_ASND_SDO_CMD_RESPONSE_FILTER 0x80
730 #define EPL_ASND_SDO_CMD_RESPONSE_RESPONSE 0
731 #define EPL_ASND_SDO_CMD_RESPONSE_REQUEST 1
733 #define EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK 0
734 #define EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER 1
736 #define EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER 0
737 #define EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER 1
738 #define EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT 2
739 #define EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE 3
741 #define EPL_ASND_SDO_COMMAND_NOT_IN_LIST 0x00
742 #define EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX 0x01
743 #define EPL_ASND_SDO_COMMAND_READ_BY_INDEX 0x02
744 #define EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX 0x03
745 #define EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX 0x04
746 #define EPL_ASND_SDO_COMMAND_WRITE_BY_NAME 0x05
747 #define EPL_ASND_SDO_COMMAND_READ_BY_NAME 0x06
748 #define EPL_ASND_SDO_COMMAND_FILE_WRITE 0x20
749 #define EPL_ASND_SDO_COMMAND_FILE_READ 0x21
750 #define EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX 0x31
751 #define EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX 0x32
752 #define EPL_ASND_SDO_COMMAND_MAXIMUM_SEGMENT_SIZE 0x70
753 #define EPL_ASND_SDO_COMMAND_LINK_NAME_TO_INDEX 0x71
756 #define EPL_SOD_CYLE_LEN 0x1006
757 #define EPL_SOD_PDO_RX_COMM 0x1400
758 #define EPL_SOD_PDO_RX_MAPP 0x1600
759 #define EPL_SOD_PDO_TX_COMM 0x1800
760 #define EPL_SOD_PDO_TX_MAPP 0x1A00
761 #define EPL_SDO_SERVER_CONT 0x1200
762 #define EPL_SDO_CLIENT_CONT 0x1280
763 #define EPL_SOD_ERR_HISTORY 0x1003
764 #define EPL_SOD_STORE_PARAM 0x1010
765 #define EPL_SOD_RESTORE_PARAM 0x1011
766 #define EPL_SOD_HEARTBEAT_TMN 0x1016
767 #define EPL_SOD_IDENTITY_OBJECT 0x1018
768 #define EPL_SOD_VERIFY_CONF 0x1020
769 #define EPL_SOD_INT_GRP 0x1030
770 #define EPL_SOD_RLATENCY_DIFF 0x1050
771 #define EPL_SOD_TELEG_Count 0x1101
772 #define EPL_SOD_ERR_STAT 0x1102
773 #define EPL_SOD_STORE_DCF_LST 0x1F20
774 #define EPL_SOD_STORE_CFM_FMT 0x1F21
775 #define EPL_SOD_STORE_CON_LST 0x1F22
776 #define EPL_SOD_STORE_DEV_FILE 0x1F23
777 #define EPL_SOD_STORE_DEV_FMT 0x1F24
778 #define EPL_SOD_CONF_REQ 0x1F25
779 #define EPL_SOD_CONF_DATE 0x1F26
780 #define EPL_SOD_CONF_TIME 0x1F27
781 #define EPL_SOD_CONF_ID 0x1F28
782 #define EPL_SOD_DL_PROG_DATA 0x1F50
783 #define EPL_SOD_DL_PROG_CTRL 0x1F51
784 #define EPL_SOD_LOC_SW 0x1F52
785 #define EPL_SOD_MN_SW_DATE 0x1F53
786 #define EPL_SOD_MN_SW_TIME 0x1F54
787 #define EPL_SOD_PROC_IMG 0x1F70
788 #define EPL_SOD_NMT_NODE 0x1F81
789 #define EPL_SOD_DEVICE_TYPE_LST 0x1F84
790 #define EPL_SOD_VENDORID_LST 0x1F85
791 #define EPL_SOD_PRODUCTEC_LST 0x1F86
792 #define EPL_SOD_REVISION_NO_LST 0x1F87
793 #define EPL_SOD_SERIAL_NO_LST 0x1F88
794 #define EPL_SOD_BOOT_TIME 0x1F89
795 #define EPL_SOD_CYCLE_TIME 0x1F8A
796 #define EPL_SOD_PREQ_PAYLOAD 0x1F8B
797 #define EPL_SOD_PRES_PAYLOAD 0x1F8D
798 #define EPL_SOD_NODE_STATE 0x1F8E
799 #define EPL_SOD_NODE_EXP_STATE 0x1F8F
800 #define EPL_SOD_CNRES_TMOUT 0x1F92
801 #define EPL_SOD_MULT_CYCL 0x1F9B
802 #define EPL_SOD_ISO_SLOT_ASSIGN 0x1F9C
803 #define EPL_SOD_NAT_TABLE 0x1D00
804 #define EPL_SOD_IP_ADD_TABLE 0x1E40
805 #define EPL_SOD_ROUTING_TABLE 0x1E90
806 #define EPL_SOD_ACL_IN_TABLE 0x1ED0
807 #define EPL_SOD_ACL_OUT_TABLE 0x1EE0
808 #define EPL_SOD_CYLE_LEN 0x1006
809 #define EPL_NMT_DEVICE_TYPE 0x1000
810 #define EPL_ERR_ERROR_REGISTER 0x1001
811 #define EPL_MANUFACT_DEV_NAME 0x1008
812 #define EPL_MANUFACT_HW_VERS 0x1009
813 #define EPL_MANUFACT_SW_VERS 0x100A
814 #define EPL_STORE_DEV_FILE 0x1021
815 #define EPL_STORE_DEV_FORMAT 0x1022
816 #define EPL_INT_GROUP 0x1300
817 #define EPL_INT_INDEX 0x1301
818 #define EPL_INT_DESC 0x1302
819 #define EPL_VERSION 0x1F83
820 #define EPL_CN_ETH_TIMEOUT 0x1F99
821 #define EPL_HOST_NAME 0x1F9A
822 #define EPL_CN_LINK_CUM 0x1C10
823 #define EPL_CN_JITTER 0x1C13
824 #define EPL_LOSS_OF_FRAME 0x1C14
826 static const range_string sod_cmd_str
[] = {
827 {EPL_SOD_PDO_RX_COMM
, 0x14FF, "0x1400"},
828 {EPL_SOD_PDO_RX_MAPP
, 0x16FF, "0x1600"},
829 {EPL_SOD_PDO_TX_COMM
, 0x18FF, "0x1800"},
830 {EPL_SOD_PDO_TX_MAPP
, 0x1AFF, "0x1A00"},
831 {EPL_SDO_SERVER_CONT
, 0x1279, "0x1200"},
832 {EPL_SDO_CLIENT_CONT
, 0x12FF, "0x1280"},
833 {EPL_SOD_NAT_TABLE
, 0x1DFF, "0x1D00"},
834 {EPL_SOD_IP_ADD_TABLE
, 0x1E49, "0x1E40"},
835 {EPL_SOD_ROUTING_TABLE
, 0x1ECF, "0x1E90"},
836 {EPL_SOD_ACL_IN_TABLE
, 0x1EDF, "0x1ED0"},
837 {EPL_SOD_ACL_OUT_TABLE
, 0x1EEF, "0x1EE0"},
841 static const value_string sod_cmd_str_val
[] = {
842 {EPL_SOD_PDO_RX_COMM
, "0x1400"},
843 {EPL_SOD_PDO_RX_MAPP
, "0x1600"},
844 {EPL_SOD_PDO_TX_COMM
, "0x1800"},
845 {EPL_SOD_PDO_TX_MAPP
, "0x1A00"},
846 {EPL_SDO_SERVER_CONT
, "0x1200"},
847 {EPL_SDO_CLIENT_CONT
, "0x1280"},
848 {EPL_SOD_NAT_TABLE
, "0x1D00"},
849 {EPL_SOD_IP_ADD_TABLE
, "0x1E40"},
850 {EPL_SOD_ROUTING_TABLE
, "0x1E90"},
851 {EPL_SOD_ACL_IN_TABLE
, "0x1ED0"},
852 {EPL_SOD_ACL_OUT_TABLE
, "0x1EE0"},
856 static const value_string sod_cmd_sub_str_val
[] = {
857 {EPL_SOD_ERR_HISTORY
, "0x1003"},
858 {EPL_SOD_HEARTBEAT_TMN
, "0x1016"},
859 {EPL_SOD_STORE_DCF_LST
, "0x1F20"},
860 {EPL_SOD_STORE_CFM_FMT
, "0x1F21"},
861 {EPL_SOD_STORE_CON_LST
, "0x1F22"},
862 {EPL_SOD_STORE_DEV_FILE
, "0x1F23"},
863 {EPL_SOD_STORE_DEV_FMT
, "0x1F24"},
864 {EPL_SOD_CONF_REQ
, "0x1F25"},
865 {EPL_SOD_CONF_DATE
, "0x1F26"},
866 {EPL_SOD_CONF_TIME
, "0x1F27"},
867 {EPL_SOD_CONF_ID
, "0x1F28"},
868 {EPL_SOD_DL_PROG_DATA
, "0x1F50"},
869 {EPL_SOD_DL_PROG_CTRL
, "0x1F51"},
870 {EPL_SOD_MN_SW_DATE
, "0x1F53"},
871 {EPL_SOD_MN_SW_TIME
, "0x1F54"},
872 {EPL_SOD_NMT_NODE
, "0x1F81"},
873 {EPL_SOD_DEVICE_TYPE_LST
,"0x1F84"},
874 {EPL_SOD_VENDORID_LST
, "0x1F85"},
875 {EPL_SOD_PRODUCTEC_LST
, "0x1F86"},
876 {EPL_SOD_REVISION_NO_LST
,"0x1F87"},
877 {EPL_SOD_SERIAL_NO_LST
, "0x1F88"},
878 {EPL_SOD_PREQ_PAYLOAD
, "0x1F8B"},
879 {EPL_SOD_PRES_PAYLOAD
, "0x1F8D"},
880 {EPL_SOD_NODE_STATE
, "0x1F8E"},
881 {EPL_SOD_NODE_EXP_STATE
, "0x1F8F"},
882 {EPL_SOD_CNRES_TMOUT
, "0x1F92"},
883 {EPL_SOD_MULT_CYCL
, "0x1F9B"},
884 {EPL_SOD_ISO_SLOT_ASSIGN
,"0x1F9C"},
888 static value_string_ext sod_cmd_sub_str
= VALUE_STRING_EXT_INIT(sod_cmd_sub_str_val
);
890 static const value_string sod_cmd_str_no_sub
[] = {
891 {EPL_NMT_DEVICE_TYPE
, "0x1000"},
892 {EPL_ERR_ERROR_REGISTER
, "0x1001"},
893 {EPL_SOD_CYLE_LEN
, "0x1006"},
894 {EPL_MANUFACT_DEV_NAME
, "0x1008"},
895 {EPL_MANUFACT_HW_VERS
, "0x1009"},
896 {EPL_MANUFACT_SW_VERS
, "0x100A"},
897 {EPL_STORE_DEV_FILE
, "0x1021"},
898 {EPL_STORE_DEV_FORMAT
, "0x1022"},
899 {EPL_INT_GROUP
, "0x1300"},
900 {EPL_INT_INDEX
, "0x1301"},
901 {EPL_INT_DESC
, "0x1302"},
902 {EPL_CN_LINK_CUM
, "0x1C10"},
903 {EPL_CN_JITTER
, "0x1C13"},
904 {EPL_LOSS_OF_FRAME
, "0x1C14"},
905 {EPL_VERSION
, "0x1F83"},
906 {EPL_CN_ETH_TIMEOUT
, "0x1F99"},
907 {EPL_HOST_NAME
, "0x1F9A"},
911 static value_string_ext sod_cmd_no_sub
= VALUE_STRING_EXT_INIT(sod_cmd_str_no_sub
);
913 static const value_string sod_idx_names
[] = {
914 /* SDO directory names */
915 {0x10000000, "NMT_DeviceType_U32"},
916 {0x10010000, "ERR_ErrorRegister_U8"},
917 {0x10030000, "ERR_History_ADOM"},
918 {0x10030001, "ErrorEntry_DOM"},
919 {0x10060000, "NMT_CycleLen_U32"},
920 {0x10080000, "NMT_ManufactDevName_VS"},
921 {0x10090000, "NMT_ManufactHwVers_VS"},
922 {0x100A0000, "NMT_ManufactSwVers_VS"},
923 {0x10100000, "NMT_StoreParam_REC"},
924 {0x10100001, "AllParam_U32"},
925 {0x10100002, "CommunicationParam_U32"},
926 {0x10100003, "ApplicationParam_U32"},
927 {0x10100004, "ManufacturerParam_XXh_U32"},
929 {0x10110000, "NMT_RestoreDefParam_REC"},
930 {0x10110001, "AllParam_U32"},
931 {0x10110002, "CommunicationParam_U32"},
932 {0x10110003, "ApplicationParam_U32"},
933 {0x10110004, "ManufacturerParam_XXh_U32"},
935 {0x10160000, "NMT_ConsumerHeartbeatTime_AU32"},
936 {0x10160001, "HeartbeatDescription"},
938 {0x10180000, "NMT_IdentityObject_REC" },
939 {0x10180001, "VendorId_U32" },
940 {0x10180002, "ProductCode_U32" },
941 {0x10180003, "RevisionNo_U32" },
942 {0x10180004, "SerialNo_U32" },
944 {0x10200000, "CFM_VerifyConfiguration_REC"},
945 {0x10200001, "ConfDate_U32"},
946 {0x10200002, "ConfTime_U32"},
947 {0x10200003, "ConfId_U32"},
948 {0x10200004, "VerifyConfInvalid_BOOL"},
950 {0x10210000, "CFM_StoreDevDescrFile_DOM"},
951 {0x10220000, "CFM_StoreDevDescrFormat_U16"},
953 {0x10300000, "NMT_InterfaceGroup_XX_REC"},
954 {0x10300001, "InterfaceIndex_U16"},
955 {0x10300002, "InterfaceDescription_VSTR"},
956 {0x10300003, "InterfaceType_U8"},
957 {0x10300004, "InterfaceMtu_U16"},
958 {0x10300005, "InterfacePhysAddress_OSTR"},
959 {0x10300006, "InterfaceName_VSTR"},
960 {0x10300007, "InterfaceOperStatus_U8"},
961 {0x10300008, "InterfaceAdminState_U8"},
962 {0x10300009, "Valid_BOOL"},
964 {0x10500000, "NMT_RelativeLatencyDiff_AU32"},
965 /* TODO: same value, so effectively hidden. Is there another value?
966 {0x10500000, "RelativeLatencyDiff"}, */
968 {0x11010000, "DIA_NMTTelegrCount_REC"},
969 {0x11010001, "IsochrCyc_U32"},
970 {0x11010002, "IsochrRx_U32"},
971 {0x11010003, "IsochrTx_U32"},
972 {0x11010004, "AsyncRx_U32"},
973 {0x11010005, "AsyncTx_U32"},
974 {0x11010006, "SdoRx_U32"},
975 {0x11010007, "SdoTx_U32"},
976 {0x11010008, "Status_U32"},
978 {0x11020000, "DIA_ERRStatistics_REC"},
979 {0x11020001, "HistoryEntryWrite_U32"},
980 {0x11020002, "EmergencyQueueWrite_U32"},
981 {0x11020003, "EmergencyQueueOverflow_U32"},
982 {0x11020004, "StatusEntryChanged_U32"},
983 {0x11020005, "StaticErrorBitFieldChanged_U32"},
984 {0x11020006, "ExceptionResetEdgePos_U32"},
985 {0x11020007, "ExceptionNewEdge_U32"},
987 {0x12000000, "SDO_ServerContainerParam"},
988 {0x12000001, "ClientNodeID_U8"},
989 {0x12000002, "ServerNodeID_U8"},
990 {0x12000003, "ContainerLen_U8"},
991 {0x12000004, "HistorySize_U8"},
993 {0x12800000, "SDO_ClientContainerParam"},
994 {0x12800001, "ClientNodeID_U8"},
995 {0x12800002, "ServerNodeID_U8"},
996 {0x12800003, "ContainerLen_U8"},
997 {0x12800004, "HistorySize_U8"},
998 {0x12800005, "Reserved"},
1000 {0x13000000, "SDO_SequLayerTimeout_U32"},
1001 {0x13010000, "SDO_CmdLayerTimeout_U32"},
1002 {0x13020000, "SDO_SequLayerNoAck_U32"},
1004 {0x14000000, "PDO_RxCommParam"},
1005 {0x14000001, "NodeID_U8"},
1006 {0x14000002, "MappingVersion_U8"},
1008 {0x16000000, "PDO_RxMappParam"},
1009 {0x16000001, "ObjectMapping"},
1011 {0x18000000, "PDO_TxCommParam"},
1012 {0x18000001, "NodeID_U8"},
1013 {0x18000002, "MappingVersion"},
1015 {0x1A000000, "PDO_TxMappParam"},
1016 {0x1A000001, "ObjectMapping"},
1018 {0x1C0A0000, "DLL_CNCollision_REC"},
1019 {0x1C0A0001, "CumulativeCnt_U32"},
1020 {0x1C0A0002, "ThresholdCnt_U32"},
1021 {0x1C0A0003, "Threshold_U32"},
1023 {0x1C0B0000, "DLL_CNLossSoC_REC"},
1024 {0x1C0B0001, "CumulativeCnt_U32"},
1025 {0x1C0B0002, "ThresholdCnt_U32"},
1026 {0x1C0B0003, "Threshold_U32"},
1028 {0x1C0C0000, "DLL_CNLossSoA_REC"},
1029 {0x1C0C0001, "CumulativeCnt_U32"},
1030 {0x1C0C0002, "ThresholdCnt_U32"},
1031 {0x1C0C0003, "Threshold_U32"},
1033 {0x1C0D0000, "DLL_CNLossPReq_REC"},
1034 {0x1C0D0001, "CumulativeCnt_U32"},
1035 {0x1C0D0002, "ThresholdCnt_U32"},
1036 {0x1C0D0003, "Threshold_U32"},
1038 {0x1C0E0000, "DLL_CNSoCJitter_REC"},
1039 {0x1C0E0001, "CumulativeCnt_U32"},
1040 {0x1C0E0002, "ThresholdCnt_U32"},
1041 {0x1C0E0003, "Threshold_U32"},
1043 {0x1C0F0000, "DLL_CNCRCError_REC"},
1044 {0x1C0F0001, "CumulativeCnt_U32"},
1045 {0x1C0F0002, "ThresholdCnt_U32"},
1046 {0x1C0F0003, "Threshold_U32"},
1048 {0x1C100000, "DLL_CNLossOfLinkCum_U32"},
1049 {0x1C130000, "DLL_CNSoCJitterRange_U32"},
1050 {0x1C140000, "DLL_LossOfFrameTolerance_U32"},
1052 {0x1D000000, "RT1_NatTable"},
1053 {0x1D000001, "EplIpAddr_IPAD"},
1054 {0x1D000002, "ExtIpAddr_IPAD"},
1055 {0x1D000003, "Mask_IPAD"},
1056 {0x1D000004, "Type_U8"},
1058 {0x1E400000, "NWL_IpAddrTable"},
1059 {0x1E400001, "IfIndex_U16"},
1060 {0x1E400002, "Addr_IPAD"},
1061 {0x1E400003, "NetMask_IPAD"},
1062 {0x1E400004, "ReasmMaxSize_U16"},
1063 {0x1E400005, "DefaultGateway_IPAD"},
1064 {0x1E4A0000, "NWL_IpGroup_REC"},
1065 {0x1E4A0001, "Forwarding_BOOL"},
1066 {0x1E4A0002, "DefaultTTL_U16"},
1067 {0x1E4A0003, "ForwardDatagrams_U32"},
1068 {0x1E800000, "RT1_EplRouter_REC"},
1069 {0x1E800001, "EnableNat_BOOL"},
1070 {0x1E800002, "EnablePacketFiltering_BOOL"},
1071 {0x1E810000, "RT1_SecurityGroup_REC"},
1072 {0x1E810001, "FwdTablePolicy_U8"},
1073 {0x1E810002, "InTablePolicy_U8"},
1074 {0x1E810003, "OutTablePolicy_U8"},
1076 {0x1E900000, "RT1_IpRoutingTable"},
1077 {0x1E900001, "IpForwardDest_IPAD"},
1078 {0x1E900002, "IpForwardMask_IPAD"},
1079 {0x1E900003, "IpForwardNextHop_IPAD"},
1080 {0x1E900004, "IpForwardType_U8"},
1081 {0x1E900005, "IpForwardAge_U32"},
1082 {0x1E900006, "IpForwardItfIndex_U16"},
1083 {0x1E900007, "IpForwardMetric1_S32"},
1085 {0x1ED00000, "RT1_AclInTable"},
1086 {0x1ED00001, "SrcIp_IPAD"},
1087 {0x1ED00002, "SrcMask_IPAD"},
1088 {0x1ED00003, "DstIp_IPAD"},
1089 {0x1ED00004, "DstMask_IPAD"},
1090 {0x1ED00005, "Protocol_U8"},
1091 {0x1ED00006, "SrcPort_U16"},
1092 {0x1ED00007, "DstPort_U16"},
1093 {0x1ED00008, "SrcMac_MAC"},
1094 {0x1ED00009, "Target_U8"},
1096 {0x1EE00000, "RT1_AclOutTable"},
1097 {0x1EE00001, "SrcIp_IPAD"},
1098 {0x1EE00002, "SrcMask_IPAD"},
1099 {0x1EE00003, "DstIp_IPAD"},
1100 {0x1EE00004, "DstMask_IPAD"},
1101 {0x1EE00005, "Protocol_U8"},
1102 {0x1EE00006, "SrcPort_U16"},
1103 {0x1EE00007, "DstPort_U16"},
1104 {0x1EE00008, "SrcMac_MAC"},
1105 {0x1EE00009, "Target_U8"},
1107 {0x1F200000, "CFM_StoreDcfList_ADOM"},
1108 {0x1F200001, "CNDcf"},
1109 {0x1F210000, "CFM_DcfStorageFormatList_AU8"},
1110 {0x1F210001, "CNDcfFormat"},
1111 {0x1F220000, "CFM_ConciseDcfList_ADOM"},
1112 {0x1F220001, "CNConciseDcfData"},
1113 {0x1F230000, "CFM_StoreDevDescrFileList_ADOM"},
1114 {0x1F230001, "CNDevDescrFile"},
1115 {0x1F240000, "CFM_DevDescrFileFormatList_AU8"},
1116 {0x1F240001, "CNDevDescrFileFormat"},
1117 {0x1F250000, "CFM_ConfCNRequest_AU32"},
1118 {0x1F250001, "CNConfigurationRequest"},
1119 {0x1F260000, "CFM_ExpConfDateList_AU32"},
1120 {0x1F260001, "CNConfigurationDate"},
1121 {0x1F270000, "CFM_ExpConfTimeList_AU32"},
1122 {0x1F270001, "CNConfigurationTime"},
1123 {0x1F280000, "CFM_ExpConfIdList_AU32"},
1124 {0x1F280001, "CNConfigurationId"},
1126 {0x1F500000, "PDL_DownloadProgData_ADOM"},
1127 {0x1F500001, "Program"},
1128 {0x1F510000, "PDL_ProgCtrl_AU8"},
1129 {0x1F510001, "ProgCtrl"},
1130 {0x1F520000, "PDL_LocVerApplSw_REC"},
1131 {0x1F520001, "ApplSwDate_U32"},
1132 {0x1F520002, "ApplSwTime_U32"},
1133 {0x1F530000, "PDL_MnExpAppSwDateList_AU32"},
1134 {0x1F530001, "AppSwDate"},
1135 {0x1F540000, "PDL_MnExpAppSwTimeList_AU32"},
1136 {0x1F540001, "AppSwTime"},
1138 {0x1F700000, "INP_ProcessImage_REC"},
1139 {0x1F700001, "SelectedRange_U32"},
1140 {0x1F700002, "ProcessImageDomain_DOM"},
1142 {0x1F800000, "NMT_StartUp_U32"},
1143 {0x1F810000, "NMT_NodeAssignment_AU32"},
1144 {0x1F810001, "NodeAssignment"},
1145 {0x1F820000, "NMT_FeatureFlags_U32"},
1146 {0x1F830000, "NMT_EPLVersion_U8"},
1147 {0x1F840000, "NMT_MNDeviceTypeIdList_AU32"},
1148 {0x1F840001, "CNDeviceTypeId"},
1149 {0x1F850000, "NMT_MNVendorIdList_AU32"},
1150 {0x1F850001, "CNVendorId"},
1151 {0x1F860000, "NMT_MNProductCodeList_AU32"},
1152 {0x1F860001, "CNProductCode"},
1153 {0x1F870000, "NMT_MNRevisionNoList_AU32"},
1154 {0x1F870001, "CNRevisionNo"},
1155 {0x1F880000, "NMT_MNSerialNoList_AU32"},
1156 {0x1F880001, "CNSerialNo"},
1158 {0x1F890000, "NMT_BootTime_REC"},
1159 {0x1F890001, "MNWaitNotAct_U32"},
1160 {0x1F890002, "MNTimeoutPreOp1_U32"},
1161 {0x1F890003, "MNWaitPreOp1_U32"},
1162 {0x1F890004, "MNTimeoutPreOp2_U32"},
1163 {0x1F890005, "MNTimeoutReadyToOp_U32"},
1164 {0x1F890006, "MNIdentificationTimeout_U32"},
1165 {0x1F890007, "MNSoftwareTimeout_U32"},
1166 {0x1F890008, "MNConfigurationTimeout_U32"},
1167 {0x1F890009, "MNStartCNTimeout_U32"},
1168 {0x1F89000A, "MNSwitchOverPriority_U32"},
1169 {0x1F89000B, "MNSwitchOverDelay_U32"},
1170 {0x1F89000C, "MNSwitchOverCycleDivider_U32"},
1172 {0x1F8A0000, "NMT_MNCycleTiming_REC"},
1173 {0x1F8A0001, "WaitSoCPReq_U32"},
1174 {0x1F8A0002, "AsyncSlotTimeout_U32"},
1175 {0x1F8A0003, "ASndMaxNumber"},
1177 {0x1F8B0000, "NMT_MNPReqPayloadLimitList_AU16"},
1178 {0x1F8B0001, "CNPReqPayload"},
1179 {0x1F8C0000, "NMT_CurrNMTState_U8"},
1180 {0x1F8D0000, "NMT_PResPayloadLimitList_AU16"},
1181 {0x1F8D0001, "PResPayloadLimit"},
1182 {0x1F8E0000, "NMT_MNNodeCurrState_AU8"},
1183 {0x1F8E0001, "CurrState"},
1184 {0x1F8F0000, "NMT_MNNodeExpState_AU8"},
1185 {0x1F8F0001, "ExpState"},
1187 {0x1F920000, "NMT_MNCNPResTimeout_AU32"},
1188 {0x1F920001, "CNResTimeout"},
1190 {0x1F930000, "NMT_EPLNodeID_REC"},
1191 {0x1F930001, "NodeID_U8"},
1192 {0x1F930002, "NodeIDByHW_BOOL"},
1193 {0x1F930003, "SWNodeID_U8"},
1195 {0x1F980000, "NMT_CycleTiming_REC"},
1196 {0x1F980001, "IsochrTxMaxPayload_U16"},
1197 {0x1F980002, "IsochrRxMaxPayload_U16"},
1198 {0x1F980003, "PResMaxLatency_U32"},
1199 {0x1F980004, "PReqActPayloadLimit_U16"},
1200 {0x1F980005, "PResActPayloadLimit_U16"},
1201 {0x1F980006, "ASndMaxLatency_U32"},
1202 {0x1F980007, "MultiplCycleCnt_U8"},
1203 {0x1F980008, "AsyncMTU_U16"},
1204 {0x1F980009, "Prescaler_U16"},
1205 {0x1F98000A, "PResMode_U8"},
1206 {0x1F98000B, "PResTimeFirst_U32"},
1207 {0x1F98000C, "PResTimeSecond_U32"},
1208 {0x1F98000D, "SyncMNDelayFirst_U32"},
1209 {0x1F98000E, "SyncMNDelaySecond_U32"},
1211 {0x1F990000, "NMT_CNBasicEthernetTimeout_U32"},
1212 {0x1F9A0000, "NMT_HostName_VSTR"},
1213 {0x1F9B0000, "NMT_MultiplCycleAssign_AU8"},
1214 {0x1F9B0001, "CycleNo"},
1215 {0x1F9C0000, "NMT_IsochrSlotAssign_AU8"},
1216 {0x1F9C0001, "NodeId"},
1217 {0x1F9E0000, "NMT_ResetCmd_U8"},
1218 {0x1F9F0000, "NMT_RequestCmd_REC"},
1219 {0x1F9F0001, "Release_BOOL"},
1220 {0x1F9F0002, "CmdID_U8"},
1221 {0x1F9F0003, "CmdTarget_U8"},
1222 {0x1F9F0004, "CmdData_DOM"},
1227 static value_string_ext sod_index_names
= VALUE_STRING_EXT_INIT(sod_idx_names
);
1229 /* SDO - Abort Transfer */
1230 static const value_string sdo_cmd_abort_code
[] = {
1231 {0x05030000, "reserved" },
1232 {0x05040000, "SDO protocol timed out." },
1233 {0x05040001, "Client/server Command ID not valid or unknown." },
1234 {0x05040002, "Invalid block size." },
1235 {0x05040003, "Invalid sequence number." },
1236 {0x05040004, "reserved" },
1237 {0x05040005, "Out of memory." },
1238 {0x06010000, "Unsupported access to an object." },
1239 {0x06010001, "Attempt to read a write-only object." },
1240 {0x06010002, "Attempt to write a read-only object." },
1241 {0x06020000, "Object does not exist in the object dictionary." },
1242 {0x06040041, "Object cannot be mapped to the PDO." },
1243 {0x06040042, "The number and length of the objects to be mapped would exceed PDO length." },
1244 {0x06040043, "General parameter incompatibility." },
1245 {0x06040047, "General internal incompatibility in the device." },
1246 {0x06060000, "Access failed due to a hardware error." },
1247 {0x06070010, "Data type does not match, length of service parameter does not match." },
1248 {0x06070012, "Data type does not match, length of service parameter too high." },
1249 {0x06070013, "Data type does not match, length of service parameter too low." },
1250 {0x06090011, "Sub-index does not exist." },
1251 {0x06090030, "Value range of parameter exceeded (only for write access)." },
1252 {0x06090031, "Value of parameter written too high." },
1253 {0x06090032, "Value of parameter written too low." },
1254 {0x06090036, "Maximum value is less then minimum value." },
1255 {0x08000000, "General error" },
1256 {0x08000020, "Data cannot be transferred or stored to the application." },
1257 {0x08000021, "Data cannot be transferred or stored to the application because of local control." },
1258 {0x08000022, "Data cannot be transferred or stored to the application because of the present device state." },
1259 {0x08000023, "Object dictionary dynamic generation fails or no object dictionary is present." },
1260 {0x08000024, "EDS, DCF or Concise DCF Data set empty." },
1263 static value_string_ext sdo_cmd_abort_code_ext
= VALUE_STRING_EXT_INIT(sdo_cmd_abort_code
);
1265 static const value_string epl_sdo_asnd_cmd_response
[] = {
1266 {EPL_ASND_SDO_CMD_RESPONSE_RESPONSE
, "Request" },
1267 {EPL_ASND_SDO_CMD_RESPONSE_REQUEST
, "Response" },
1271 static const value_string epl_sdo_asnd_cmd_abort
[] = {
1272 {EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK
, "Transfer OK" },
1273 {EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER
, "Abort Transfer" },
1277 static const value_string epl_sdo_asnd_cmd_segmentation
[] = {
1278 {EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER
, "Expedited Transfer" },
1279 {EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
, "Initiate Transfer" },
1280 {EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT
, "Segment" },
1281 {EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE
, "Transfer Complete" },
1285 static const value_string epl_sdo_asnd_cmd_segmentation_abbr
[] = {
1286 {EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER
, "EX" },
1287 {EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
, "SI" },
1288 {EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT
, "ST" },
1289 {EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE
, "SC" },
1293 static const value_string epl_sdo_asnd_commands
[] = {
1294 {EPL_ASND_SDO_COMMAND_NOT_IN_LIST
, "Not in List" },
1295 {EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
, "Write by Index" },
1296 {EPL_ASND_SDO_COMMAND_READ_BY_INDEX
, "Read by Index" },
1297 {EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX
, "Write All by Index" },
1298 {EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX
, "Read All by Index" },
1299 {EPL_ASND_SDO_COMMAND_WRITE_BY_NAME
, "Write by Name" },
1300 {EPL_ASND_SDO_COMMAND_READ_BY_NAME
, "Read by Name" },
1301 {EPL_ASND_SDO_COMMAND_FILE_WRITE
, "File Write" },
1302 {EPL_ASND_SDO_COMMAND_FILE_READ
, "File Read" },
1303 {EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
, "Write Multiple Parameter by Index" },
1304 {EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX
, "Read Multiple Parameter by Index" },
1305 {EPL_ASND_SDO_COMMAND_MAXIMUM_SEGMENT_SIZE
, "Maximum Segment Size" },
1306 {EPL_ASND_SDO_COMMAND_LINK_NAME_TO_INDEX
, "Link objects only accessible via name to an index/sub-index"},
1310 static value_string_ext epl_sdo_asnd_commands_ext
= VALUE_STRING_EXT_INIT(epl_sdo_asnd_commands
);
1312 static const value_string epl_sdo_asnd_commands_short
[] = {
1313 {EPL_ASND_SDO_COMMAND_NOT_IN_LIST
, "NotInList" },
1314 {EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
, "WriteByIndex" },
1315 {EPL_ASND_SDO_COMMAND_READ_BY_INDEX
, "ReadByIndex" },
1316 {EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX
, "WriteAllByIndex" },
1317 {EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX
, "ReadAllByIndex" },
1318 {EPL_ASND_SDO_COMMAND_WRITE_BY_NAME
, "WriteByName" },
1319 {EPL_ASND_SDO_COMMAND_READ_BY_NAME
, "ReadByName" },
1320 {EPL_ASND_SDO_COMMAND_FILE_WRITE
, "FileWrite" },
1321 {EPL_ASND_SDO_COMMAND_FILE_READ
, "FileRead" },
1322 {EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
, "WriteMultipleParam" },
1323 {EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX
, "ReadMultipleParam" },
1328 static value_string_ext epl_sdo_asnd_commands_short_ext
= VALUE_STRING_EXT_INIT(epl_sdo_asnd_commands_short
);
1331 static const char* addr_str_cn
= " (Controlled Node)";
1332 static const char* addr_str_res
= " (reserved)";
1334 struct object_mapping
{
1338 } pdo
, /* The PDO to be mapped */
1339 param
; /* The ObjectMapping OD entry that mapped it */
1341 uint16_t bit_offset
;
1342 uint16_t no_of_bits
;
1346 uint32_t first
, last
;
1347 } frame
; /* frames for which object_mapping applies */
1348 const struct od_entry
*info
;
1349 const char *index_name
;
1352 #define OBJECT_MAPPING_INITIALIZER { { 0, 0 }, { 0, 0 }, 0, 0, 0, { 0, 0 }, 0, 0, { 0 } }
1354 #define CONVO_FOR_RESPONSE 1
1355 #define CONVO_FOR_REQUEST 2
1356 #define CONVO_ALWAYS_CREATE 4
1362 uint8_t sendsequence
;
1364 const char *index_name
;
1365 const struct od_entry
*info
;
1371 uint16_t device_type
;
1372 uint32_t response_time
;
1374 uint32_t product_code
;
1376 unsigned generation
; /* FIXME remove */
1377 wmem_array_t
*TPDO
; /* CN->MN */
1378 wmem_array_t
*RPDO
; /* MN->CN */
1380 struct profile
*profile
;
1382 uint32_t last_frame
;
1383 uint8_t next_read_req
;
1386 struct read_req read_reqs
[4];
1388 /* In lieu of allocating an unknown number of read requests, we'll keep a ring
1389 * buff of the 4 most recent ones and when a response comes we add them as packet
1395 static int dissect_epl_payload(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, int len
, const struct epl_datatype
*type
, uint8_t msgType
);
1396 static int dissect_epl_soc(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1397 static int dissect_epl_preq(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1398 static int dissect_epl_pres(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1399 static int dissect_epl_soa(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1401 static int dissect_epl_asnd_ires(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1402 static int dissect_epl_asnd_sres(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1403 static int dissect_epl_asnd_nmtcmd(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1404 static int dissect_epl_asnd_nmtreq(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1405 static int dissect_epl_asnd_nmtdna(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1406 static int dissect_epl_asnd(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1407 static int dissect_epl_ainv(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1409 static int dissect_epl_asnd_sdo(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1410 static int dissect_epl_asnd_resp(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
);
1411 static int dissect_epl_sdo_sequence(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t *seq
);
1412 static int dissect_epl_sdo_command(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t seq
);
1413 static int dissect_epl_sdo_command_write_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
);
1414 static int dissect_epl_sdo_command_write_multiple_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
);
1415 static int dissect_epl_sdo_command_read_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
);
1416 static int dissect_epl_sdo_command_read_multiple_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
);
1417 static int dissect_object_mapping(struct profile
*profile
, wmem_array_t
*mappings
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, uint32_t framenum
, int offset
, uint16_t idx
, uint8_t subindex
);
1419 static const char* decode_epl_address(unsigned char adr
);
1421 /* Initialize the protocol and registered fields */
1422 static int proto_epl
;
1424 static int hf_epl_mtyp
;
1425 static int hf_epl_node
;
1426 static int hf_epl_dest
;
1427 static int hf_epl_src
;
1428 static int hf_epl_payload_real
;
1430 /* available epl message types */
1431 static int hf_epl_soc
;
1432 static int hf_epl_preq
;
1433 static int hf_epl_pres
;
1434 static int hf_epl_soa
;
1435 static int hf_epl_asnd
;
1436 static int hf_epl_amni
;
1437 static int hf_epl_ainv
;
1439 static int hf_epl_soc_flags
;
1440 static int hf_epl_soc_mc
;
1441 static int hf_epl_soc_ps
;
1442 static int hf_epl_soc_dna_an
;
1443 static int hf_epl_soc_nettime
;
1444 static int hf_epl_soc_relativetime
;
1446 static int hf_epl_preq_flags
;
1447 static int hf_epl_preq_ms
;
1448 static int hf_epl_preq_ea
;
1449 static int hf_epl_preq_rd
;
1450 static int hf_epl_preq_sls
;
1451 static int hf_epl_preq_fls
;
1452 static int hf_epl_preq_pdov
;
1453 static int hf_epl_preq_size
;
1455 static int hf_epl_pres_stat_ms
;
1456 static int hf_epl_pres_stat_cs
;
1457 static int hf_epl_pres_flags
;
1458 static int hf_epl_pres_ms
;
1459 static int hf_epl_pres_en
;
1460 static int hf_epl_pres_rd
;
1461 static int hf_epl_pres_pr
;
1462 static int hf_epl_pres_rs
;
1463 static int hf_epl_pres_sls
;
1464 static int hf_epl_pres_fls
;
1465 static int hf_epl_pres_pdov
;
1466 static int hf_epl_pres_size
;
1468 static int hf_epl_soa_stat_ms
;
1469 static int hf_epl_soa_stat_cs
;
1470 static int hf_epl_soa_ea
;
1471 static int hf_epl_soa_er
;
1472 static int hf_epl_soa_svid
;
1473 static int hf_epl_soa_svtg
;
1474 static int hf_epl_soa_eplv
;
1475 static int hf_epl_soa_rrflags
;
1476 static int hf_epl_soa_rrflags_mnred
;
1477 static int hf_epl_soa_rrflags_cblred
;
1478 static int hf_epl_soa_rrflags_ringred
;
1479 static int hf_epl_soa_rrflags_ringstat
;
1482 static int hf_epl_soa_sync
;
1483 static int hf_epl_soa_mac
;
1484 static int hf_epl_soa_pre_fst
;
1485 static int hf_epl_soa_pre_sec
;
1486 static int hf_epl_soa_mnd_fst
;
1487 static int hf_epl_soa_mnd_sec
;
1488 static int hf_epl_soa_pre_tm
;
1489 static int hf_epl_soa_pre_set
;
1490 static int hf_epl_soa_pre_res
;
1491 static int hf_epl_soa_mac_end
;
1492 static int hf_epl_soa_pre_fst_end
;
1493 static int hf_epl_soa_pre_sec_end
;
1494 static int hf_epl_soa_mnd_fst_end
;
1495 static int hf_epl_soa_mnd_sec_end
;
1496 static int hf_epl_soa_pre_tm_end
;
1497 static int hf_epl_soa_dna_an_glb
;
1498 static int hf_epl_soa_dna_an_lcl
;
1501 static int hf_epl_asnd_syncResponse_sync
;
1502 static int hf_epl_asnd_syncResponse_latency
;
1503 static int hf_epl_asnd_syncResponse_node
;
1504 static int hf_epl_asnd_syncResponse_delay
;
1505 static int hf_epl_asnd_syncResponse_pre_fst
;
1506 static int hf_epl_asnd_syncResponse_pre_sec
;
1507 static int hf_epl_asnd_syncResponse_fst_val
;
1508 static int hf_epl_asnd_syncResponse_sec_val
;
1509 static int hf_epl_asnd_syncResponse_mode
;
1511 static int hf_epl_asnd_svid
;
1512 static int hf_epl_asnd_svtg
;
1513 /* static int hf_epl_asnd_data; */
1516 static int hf_epl_asnd_identresponse_en
;
1517 static int hf_epl_asnd_identresponse_ec
;
1518 static int hf_epl_asnd_identresponse_pr
;
1519 static int hf_epl_asnd_identresponse_rs
;
1520 static int hf_epl_asnd_identresponse_sls
;
1521 static int hf_epl_asnd_identresponse_fls
;
1522 static int hf_epl_asnd_identresponse_stat_ms
;
1523 static int hf_epl_asnd_identresponse_stat_cs
;
1524 static int hf_epl_asnd_identresponse_ever
;
1525 static int hf_epl_asnd_identresponse_feat
;
1526 static int hf_epl_asnd_identresponse_feat_bit0
;
1527 static int hf_epl_asnd_identresponse_feat_bit1
;
1528 static int hf_epl_asnd_identresponse_feat_bit2
;
1529 static int hf_epl_asnd_identresponse_feat_bit3
;
1530 static int hf_epl_asnd_identresponse_feat_bit4
;
1531 static int hf_epl_asnd_identresponse_feat_bit5
;
1532 static int hf_epl_asnd_identresponse_feat_bit6
;
1533 static int hf_epl_asnd_identresponse_feat_bit7
;
1534 static int hf_epl_asnd_identresponse_feat_bit8
;
1535 static int hf_epl_asnd_identresponse_feat_bit9
;
1536 static int hf_epl_asnd_identresponse_feat_bitA
;
1537 static int hf_epl_asnd_identresponse_feat_bitB
;
1538 static int hf_epl_asnd_identresponse_feat_bitC
;
1539 static int hf_epl_asnd_identresponse_feat_bitD
;
1540 static int hf_epl_asnd_identresponse_feat_bitE
;
1541 static int hf_epl_asnd_identresponse_feat_bitF
;
1542 static int hf_epl_asnd_identresponse_feat_bit10
;
1543 static int hf_epl_asnd_identresponse_feat_bit11
;
1544 static int hf_epl_asnd_identresponse_feat_bit12
;
1545 static int hf_epl_asnd_identresponse_feat_bit13
;
1546 static int hf_epl_asnd_identresponse_feat_bit14
;
1547 static int hf_epl_asnd_identresponse_feat_bit21
;
1548 static int hf_epl_asnd_identresponse_mtu
;
1549 static int hf_epl_asnd_identresponse_pis
;
1550 static int hf_epl_asnd_identresponse_pos
;
1551 static int hf_epl_asnd_identresponse_rst
;
1552 static int hf_epl_asnd_identresponse_dt
;
1553 static int hf_epl_asnd_identresponse_dt_add
;
1554 static int hf_epl_asnd_identresponse_vid
;
1555 static int hf_epl_asnd_identresponse_productcode
;
1556 static int hf_epl_asnd_identresponse_rno
;
1557 static int hf_epl_asnd_identresponse_sno
;
1558 static int hf_epl_asnd_identresponse_vex1
;
1559 static int hf_epl_asnd_identresponse_vcd
;
1560 static int hf_epl_asnd_identresponse_vct
;
1561 static int hf_epl_asnd_identresponse_ad
;
1562 static int hf_epl_asnd_identresponse_at
;
1563 static int hf_epl_asnd_identresponse_ipa
;
1564 static int hf_epl_asnd_identresponse_snm
;
1565 static int hf_epl_asnd_identresponse_gtw
;
1566 static int hf_epl_asnd_identresponse_hn
;
1567 static int hf_epl_asnd_identresponse_vex2
;
1570 static int hf_epl_asnd_statusresponse_en
;
1571 static int hf_epl_asnd_statusresponse_ec
;
1572 static int hf_epl_asnd_statusresponse_pr
;
1573 static int hf_epl_asnd_statusresponse_rs
;
1574 static int hf_epl_asnd_statusresponse_sls
;
1575 static int hf_epl_asnd_statusresponse_fls
;
1576 static int hf_epl_asnd_statusresponse_stat_ms
;
1577 static int hf_epl_asnd_statusresponse_stat_cs
;
1578 /* static int hf_epl_asnd_statusresponse_seb; */
1580 /*StaticErrorBitField */
1581 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit0
;
1582 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit1
;
1583 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit2
;
1584 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit3
;
1585 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit4
;
1586 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit5
;
1587 static int hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit7
;
1588 static int hf_epl_asnd_statusresponse_seb_devicespecific_err
;
1590 /*List of Errors/Events*/
1591 /* static int hf_epl_asnd_statusresponse_el; */
1592 /* static int hf_epl_asnd_statusresponse_el_entry; */
1593 static int hf_epl_asnd_statusresponse_el_entry_type
;
1594 static int hf_epl_asnd_statusresponse_el_entry_type_profile
;
1595 static int hf_epl_asnd_statusresponse_el_entry_type_mode
;
1596 static int hf_epl_asnd_statusresponse_el_entry_type_bit14
;
1597 static int hf_epl_asnd_statusresponse_el_entry_type_bit15
;
1598 static int hf_epl_asnd_statusresponse_el_entry_code
;
1599 static int hf_epl_asnd_statusresponse_el_entry_time
;
1600 static int hf_epl_asnd_statusresponse_el_entry_add
;
1603 static int hf_epl_asnd_nmtrequest_rcid
;
1604 static int hf_epl_asnd_nmtrequest_rct
;
1605 static int hf_epl_asnd_nmtrequest_rcd
;
1608 static int hf_epl_asnd_nmtcommand_cid
;
1609 static int hf_epl_asnd_nmtcommand_cdat
;
1610 static int hf_epl_asnd_nmtcommand_resetnode_reason
;
1611 /*static int hf_epl_asnd_nmtcommand_nmtnetparameterset_mtu;*/
1612 static int hf_epl_asnd_nmtcommand_nmtnethostnameset_hn
;
1613 static int hf_epl_asnd_nmtcommand_nmtflusharpentry_nid
;
1614 static int hf_epl_asnd_nmtcommand_nmtpublishtime_dt
;
1615 static int hf_epl_asnd_nmtcommand_nmtdna
;
1616 static int hf_epl_asnd_nmtcommand_nmtdna_flags
;
1617 static int hf_epl_asnd_nmtcommand_nmtdna_ltv
;
1618 static int hf_epl_asnd_nmtcommand_nmtdna_hpm
;
1619 static int hf_epl_asnd_nmtcommand_nmtdna_nnn
;
1620 static int hf_epl_asnd_nmtcommand_nmtdna_mac
;
1621 static int hf_epl_asnd_nmtcommand_nmtdna_cnn
;
1622 static int hf_epl_asnd_nmtcommand_nmtdna_currmac
;
1623 static int hf_epl_asnd_nmtcommand_nmtdna_hubenmsk
;
1624 static int hf_epl_asnd_nmtcommand_nmtdna_currnn
;
1625 static int hf_epl_asnd_nmtcommand_nmtdna_newnn
;
1626 static int hf_epl_asnd_nmtcommand_nmtdna_leasetime
;
1629 /*Asynchronous SDO Sequence Layer*/
1630 static int hf_epl_asnd_sdo_seq
;
1631 static int hf_epl_asnd_sdo_seq_receive_sequence_number
;
1632 static int hf_epl_asnd_sdo_seq_receive_con
;
1633 static int hf_epl_asnd_sdo_seq_send_sequence_number
;
1634 static int hf_epl_asnd_sdo_seq_send_con
;
1636 /*Asynchronous SDO Command Layer*/
1637 static int hf_epl_asnd_sdo_cmd
;
1638 static int hf_epl_asnd_sdo_cmd_transaction_id
;
1639 static int hf_epl_asnd_sdo_cmd_response
;
1642 static int hf_epl_asnd_sdo_resp_in
;
1643 static int hf_epl_asnd_sdo_no_resp
;
1644 static int hf_epl_asnd_sdo_resp_to
;
1647 static int hf_epl_asnd_sdo_cmd_abort
;
1648 static int hf_epl_asnd_sdo_cmd_sub_abort
;
1649 static int hf_epl_asnd_sdo_cmd_segmentation
;
1650 static int hf_epl_asnd_sdo_cmd_command_id
;
1651 static int hf_epl_asnd_sdo_cmd_segment_size
;
1653 static int hf_epl_asnd_sdo_cmd_data_size
;
1654 static int hf_epl_asnd_sdo_cmd_data_padding
;
1655 static int hf_epl_asnd_sdo_cmd_data_index
;
1656 static int hf_epl_asnd_sdo_cmd_data_subindex
;
1657 static int hf_epl_asnd_sdo_cmd_data_mapping
;
1658 static int hf_epl_asnd_sdo_cmd_data_mapping_index
;
1659 static int hf_epl_asnd_sdo_cmd_data_mapping_subindex
;
1660 static int hf_epl_asnd_sdo_cmd_data_mapping_offset
;
1661 static int hf_epl_asnd_sdo_cmd_data_mapping_length
;
1662 /*static int hf_epl_asnd_sdo_cmd_data_response;*/
1664 static int hf_epl_asnd_sdo_cmd_reassembled
;
1665 static int hf_epl_fragments
;
1666 static int hf_epl_fragment
;
1667 static int hf_epl_fragment_overlap
;
1668 static int hf_epl_fragment_overlap_conflicts
;
1669 static int hf_epl_fragment_multiple_tails
;
1670 static int hf_epl_fragment_too_long_fragment
;
1671 static int hf_epl_fragment_error
;
1672 static int hf_epl_fragment_count
;
1673 static int hf_epl_reassembled_in
;
1674 static int hf_epl_reassembled_length
;
1675 static int hf_epl_reassembled_data
;
1676 static int hf_epl_sdo_multi_param_sub_abort
;
1678 static int hf_epl_asnd_identresponse_profile_path
;
1680 /* EPL OD Data Types */
1681 static int hf_epl_pdo
;
1682 static int hf_epl_pdo_index
;
1683 static int hf_epl_pdo_subindex
;
1685 static int hf_epl_od_meta
;
1686 static int hf_epl_od_meta_mapping_index
;
1687 static int hf_epl_od_meta_mapping_subindex
;
1688 static int hf_epl_od_meta_lifetime_start
;
1689 static int hf_epl_od_meta_lifetime_end
;
1690 static int hf_epl_od_meta_offset
;
1691 static int hf_epl_od_meta_length
;
1693 static int hf_epl_od_boolean
;
1694 static int hf_epl_od_int
;
1695 static int hf_epl_od_uint
;
1696 static int hf_epl_od_real
;
1697 static int hf_epl_od_string
;
1698 static int hf_epl_od_octet_string
;
1699 static int hf_epl_od_time
;
1701 static int hf_epl_od_time_difference
;
1702 static int hf_epl_od_domain
;
1704 static int hf_epl_od_mac
;
1705 static int hf_epl_od_ipv4
;
1707 #define EPL_PDO_TYPE_COUNT 8
1709 static const struct epl_datatype
{
1714 } epl_datatype
[] = {
1715 { "Boolean", &hf_epl_od_boolean
, ENC_LITTLE_ENDIAN
, 1 },
1717 { "Integer8", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 1 },
1718 { "Integer16", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 2 },
1719 { "Integer24", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 3 },
1720 { "Integer32", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 4 },
1721 { "Integer40", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 5 },
1722 { "Integer48", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 6 },
1723 { "Integer56", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 7 },
1724 { "Integer64", &hf_epl_od_int
, ENC_LITTLE_ENDIAN
, 8 },
1726 { "Unsigned8", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 1 },
1727 { "Unsigned16", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 2 },
1728 { "Unsigned24", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 3 },
1729 { "Unsigned32", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 4 },
1730 { "Unsigned40", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 5 },
1731 { "Unsigned48", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 6 },
1732 { "Unsigned56", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 7 },
1733 { "Unsigned64", &hf_epl_od_uint
, ENC_LITTLE_ENDIAN
, 8 },
1735 /* non-integer types */
1736 { "Real32", &hf_epl_od_real
, ENC_LITTLE_ENDIAN
, 4 },
1737 { "Real64", &hf_epl_od_real
, ENC_LITTLE_ENDIAN
, 8 },
1738 { "Visible_String", &hf_epl_od_string
, ENC_ASCII
, 0 },
1739 { "Octet_String", &hf_epl_od_octet_string
, ENC_NA
, 0 },
1740 { "Unicode_String", &hf_epl_od_string
, ENC_UCS_2
| ENC_LITTLE_ENDIAN
, 0 },
1742 { "MAC_ADDRESS", &hf_epl_od_mac
, ENC_BIG_ENDIAN
, 6 },
1743 { "IP_ADDRESS", &hf_epl_od_ipv4
, ENC_BIG_ENDIAN
, 4 },
1745 { "Domain", &hf_epl_od_domain
, ENC_NA
},
1747 { "Time_of_Day", &hf_epl_od_time
, ENC_NA
},
1748 { "Time_Diff", &hf_epl_od_time_difference
, ENC_NA
},
1750 { "NETTIME", &hf_epl_od_time
, ENC_TIME_SECS_NSECS
, 8 },
1756 static int ett_epl_fragment
;
1757 static int ett_epl_fragments
;
1759 static const fragment_items epl_frag_items
= {
1760 /* Fragment subtrees */
1763 /* Fragment fields */
1766 &hf_epl_fragment_overlap
,
1767 &hf_epl_fragment_overlap_conflicts
,
1768 &hf_epl_fragment_multiple_tails
,
1769 &hf_epl_fragment_too_long_fragment
,
1770 &hf_epl_fragment_error
,
1771 &hf_epl_fragment_count
,
1772 /* Reassembled in field */
1773 &hf_epl_reassembled_in
,
1774 /* Reassembled length field */
1775 &hf_epl_reassembled_length
,
1776 /* Reassembled data */
1777 &hf_epl_reassembled_data
,
1782 static int hf_epl_asnd_sdo_cmd_abort_code
;
1784 static int hf_epl_asnd_sdo_cmd_abort_flag
;
1785 static int hf_epl_asnd_sdo_cmd_segmentation_flag
;
1786 static int hf_epl_asnd_sdo_cmd_cmd_valid_test
;
1788 static int hf_epl_asnd_sdo_actual_command_id
;
1790 static int hf_epl_asnd_sdo_actual_segment_size
;
1791 static int hf_epl_asnd_sdo_actual_payload_size_read
;
1794 /* Initialize the subtree pointers */
1796 static int ett_epl_soc
;
1797 static int ett_epl_preq
;
1798 static int ett_epl_pres
;
1799 static int ett_epl_feat
;
1800 static int ett_epl_seb
;
1801 static int ett_epl_el
;
1802 static int ett_epl_el_entry
;
1803 static int ett_epl_el_entry_type
;
1804 static int ett_epl_sdo_entry_type
;
1805 static int ett_epl_asnd_nmt_dna
;
1807 static int ett_epl_sdo
;
1808 static int ett_epl_sdo_sequence_layer
;
1809 static int ett_epl_sdo_command_layer
;
1810 static int ett_epl_sdo_data
;
1811 static int ett_epl_asnd_sdo_cmd_data_mapping
;
1812 static int ett_epl_soa_sync
;
1813 static int ett_epl_asnd_sync
;
1815 static int ett_epl_pdo_meta
;
1817 static expert_field ei_duplicated_frame
;
1818 static expert_field ei_recvseq_value
;
1819 static expert_field ei_sendseq_value
;
1820 static expert_field ei_real_length_differs
;
1822 static dissector_handle_t epl_handle
;
1823 static dissector_handle_t epl_udp_handle
;
1825 static bool show_cmd_layer_for_duplicated
;
1826 static bool show_pdo_meta_info
;
1827 static bool use_xdc_mappings
= true;
1828 static bool interpret_untyped_as_le
= true;
1829 static bool use_sdo_mappings
= true;
1831 static int ett_epl_asnd_sdo_data_reassembled
;
1833 static reassembly_table epl_reassembly_table
;
1834 static GHashTable
*epl_duplication_table
;
1837 epl_datatype
*epl_type_to_hf(const char *name
)
1839 const struct epl_datatype
*entry
;
1840 for (entry
= epl_datatype
; entry
->name
; entry
++)
1842 if (strcmp(name
, entry
->name
) == 0)
1849 epl_address_hash(const void *a
)
1851 return add_address_to_hash(0, (const address
*)a
);
1854 epl_address_equal(const void *a
, const void *b
)
1856 return addresses_equal((const address
*)a
, (const address
*)b
);
1860 * PDO Mappings store object/subobjct pointers and thus need to be
1861 * updated after a profile change. We purge them by resetting the
1862 * memory pool. As PDO Mappings are referenced via Conversations,
1863 * we need to fix up those too. I didn't figure out how to clear
1864 * conversations yet, so till now, we keep a variable to tell us
1865 * if we have dangling pointers. Courtesy of Peter Wu.
1868 unsigned current_convo_generation
; /* FIXME remove */
1869 static wmem_allocator_t
*pdo_mapping_scope
;
1870 static struct object_mapping
*
1871 get_object_mappings(wmem_array_t
*arr
, unsigned *len
)
1873 *len
= wmem_array_get_count(arr
);
1874 return (struct object_mapping
*)wmem_array_get_raw(arr
);
1877 object_mapping_cmp(const void *_a
, const void *_b
)
1879 const struct object_mapping
*a
= (const struct object_mapping
*)_a
;
1880 const struct object_mapping
*b
= (const struct object_mapping
*)_b
;
1882 if (a
->bit_offset
< b
->bit_offset
) return -1;
1883 if (a
->bit_offset
> b
->bit_offset
) return +1;
1887 object_mapping_eq(struct object_mapping
*a
, struct object_mapping
*b
)
1889 return a
->pdo
.idx
== b
->pdo
.idx
1890 && a
->pdo
.subindex
== b
->pdo
.subindex
1891 && a
->frame
.first
== b
->frame
.first
1892 && a
->param
.idx
== b
->param
.idx
1893 && a
->param
.subindex
== b
->param
.subindex
;
1896 add_object_mapping(wmem_array_t
*arr
, struct object_mapping
*mapping
)
1898 /* let's check if this overwrites an existing mapping */
1900 /* A bit inefficient (looping backwards would be better), but it's acyclic anyway */
1901 struct object_mapping
*old
= get_object_mappings(arr
, &len
);
1902 for (i
= 0; i
< len
; i
++)
1904 if (object_mapping_eq(&old
[i
], mapping
))
1907 if (old
[i
].frame
.first
< mapping
->frame
.first
1908 && (CHECK_OVERLAP_LENGTH(old
[i
].bit_offset
, old
[i
].no_of_bits
, mapping
->bit_offset
, mapping
->no_of_bits
)
1909 || (old
[i
].param
.idx
== mapping
->param
.idx
&& old
[i
].param
.subindex
== mapping
->param
.subindex
1910 && CHECK_OVERLAP_ENDS(old
[i
].frame
.first
, old
[i
].frame
.last
, mapping
->frame
.first
, mapping
->frame
.last
))))
1912 old
[i
].frame
.last
= mapping
->frame
.first
;
1916 wmem_array_append(arr
, mapping
, 1);
1917 wmem_array_sort(arr
, object_mapping_cmp
);
1921 static wmem_map_t
*epl_profiles_by_device
, *epl_profiles_by_nodeid
, *epl_profiles_by_address
;
1922 static struct profile
*epl_default_profile
;
1923 static const char *epl_default_profile_path
= NULL
, *epl_default_profile_path_last
;
1926 profile_del_cb(wmem_allocator_t
*pool _U_
, wmem_cb_event_t event _U_
, void *_profile
)
1928 struct profile
*profile
= (struct profile
*)_profile
;
1929 if (profile
->parent_map
)
1930 wmem_map_remove(profile
->parent_map
, profile
->data
);
1931 wmem_destroy_allocator(profile
->scope
);
1936 profile_del(struct profile
*profile
)
1938 if (!profile
) return;
1939 wmem_unregister_callback(profile
->parent_scope
, profile
->cb_id
);
1940 profile_del_cb(NULL
, WMEM_CB_DESTROY_EVENT
, profile
);
1943 static struct profile
*
1944 profile_new(wmem_allocator_t
*parent_pool
)
1946 wmem_allocator_t
*pool
;
1947 struct profile
*profile
;
1949 pool
= wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE
);
1950 profile
= wmem_new0(pool
, struct profile
);
1951 profile
->cb_id
= wmem_register_callback(parent_pool
, profile_del_cb
, profile
);
1953 profile
->scope
= pool
;
1954 profile
->parent_scope
= parent_pool
;
1955 profile
->parent_map
= NULL
;
1956 profile
->objects
= wmem_map_new(pool
, g_direct_hash
, g_direct_equal
);
1957 profile
->name
= NULL
;
1958 profile
->path
= NULL
;
1959 profile
->RPDO
= wmem_array_new(pool
, sizeof (struct object_mapping
));
1960 profile
->TPDO
= wmem_array_new(pool
, sizeof (struct object_mapping
));
1961 profile
->next
= NULL
;
1966 static struct object
*object_lookup(struct profile
*profile
, uint16_t idx
);
1967 static const struct subobject
*subobject_lookup(struct object
*obj
, uint8_t subindex
);
1970 epl_profile_object_add(struct profile
*profile
, uint16_t idx
)
1972 struct object
*object
= wmem_new0(profile
->scope
, struct object
);
1974 object
->info
.idx
= idx
;
1976 wmem_map_insert(profile
->objects
, GUINT_TO_POINTER(object
->info
.idx
), object
);
1981 epl_profile_object_lookup_or_add(struct profile
*profile
, uint16_t idx
)
1983 struct object
*obj
= object_lookup(profile
, idx
);
1984 return obj
? obj
: epl_profile_object_add(profile
, idx
);
1989 epl_profile_object_mapping_add(struct profile
*profile
, uint16_t idx
, uint8_t subindex
, uint64_t mapping
)
1991 wmem_array_t
*mappings
;
1993 uint64_t mapping_le
;
1995 if (!use_xdc_mappings
)
1998 if(idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
1999 mappings
= profile
->RPDO
;
2000 else if (idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
2001 mappings
= profile
->TPDO
;
2005 mapping_le
= GUINT64_TO_LE(mapping
);
2006 tvb
= tvb_new_real_data((uint8_t*)&mapping_le
, sizeof mapping_le
, sizeof mapping_le
);
2008 return dissect_object_mapping(profile
, mappings
, NULL
, tvb
, 0, 0, idx
, subindex
) == EPL_OBJECT_MAPPING_SIZE
;
2012 epl_profile_object_mappings_update(struct profile
*profile
)
2014 bool updated_any
= false;
2015 struct object_mapping
*mappings
;
2016 wmem_array_t
*PDOs
[3], **PDO
;
2018 if (!use_xdc_mappings
)
2022 PDOs
[0] = profile
->RPDO
;
2023 PDOs
[1] = profile
->TPDO
;
2026 for (PDO
= PDOs
; *PDO
; PDO
++)
2029 len
= wmem_array_get_count(*PDO
);
2030 mappings
= (struct object_mapping
*)wmem_array_get_raw(*PDO
);
2032 for (i
= 0; i
< len
; i
++)
2034 struct object_mapping
*map
= &mappings
[i
];
2035 struct object
*mapping_obj
;
2036 const struct subobject
*mapping_subobj
;
2038 if (!(mapping_obj
= object_lookup(profile
, map
->pdo
.idx
)))
2040 map
->info
= &mapping_obj
->info
;
2041 map
->index_name
= map
->info
->name
;
2043 if (!(mapping_subobj
= subobject_lookup(mapping_obj
, map
->pdo
.subindex
)))
2045 map
->info
= &mapping_subobj
->info
;
2052 static struct read_req
*
2053 convo_read_req_get(struct epl_convo
*convo
, packet_info
*pinfo
, uint8_t SendSequenceNumber
)
2056 uint32_t seq_p_key
= (ETHERTYPE_EPL_V2
<< 16) | convo
->seq_send
;
2057 struct read_req
*req
= (struct read_req
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_epl
, seq_p_key
);
2062 for (i
= 0; i
< array_length(convo
->read_reqs
); i
++)
2064 if(convo
->read_reqs
[i
].sendsequence
== SendSequenceNumber
)
2066 req
= wmem_new(wmem_file_scope(), struct read_req
);
2067 *req
= convo
->read_reqs
[i
];
2068 p_add_proto_data(wmem_file_scope(), pinfo
, proto_epl
, seq_p_key
, req
);
2075 static struct read_req
*
2076 convo_read_req_set(struct epl_convo
*convo
, uint8_t SendSequenceNumber
)
2078 struct read_req
*slot
= &convo
->read_reqs
[convo
->next_read_req
++];
2079 convo
->next_read_req
%= array_length(convo
->read_reqs
);
2080 slot
->sendsequence
= SendSequenceNumber
;
2086 dissect_epl_pdo(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, unsigned len
, uint8_t msgType
)
2088 wmem_array_t
*mapping
= msgType
== EPL_PRES
? convo
->TPDO
: convo
->RPDO
;
2089 tvbuff_t
*payload_tvb
;
2090 unsigned rem_len
, payload_len
, payload_len_bits
;
2091 heur_dtbl_entry_t
*hdtbl_entry
= NULL
;
2093 unsigned i
, maps_count
;
2096 struct object_mapping
*mappings
= get_object_mappings(mapping
, &maps_count
);
2101 rem_len
= tvb_captured_length_remaining(tvb
, offset
);
2102 payload_tvb
= tvb_new_subset_length(tvb
, offset
, MIN(len
, rem_len
));
2103 payload_len
= tvb_captured_length_remaining(payload_tvb
, 0);
2104 payload_len_bits
= payload_len
* 8;
2105 if ( payload_len
< len
)
2107 item
= proto_tree_add_uint(epl_tree
, hf_epl_payload_real
, tvb
, offset
, payload_len
, payload_len
);
2108 proto_item_set_generated(item
);
2109 expert_add_info(pinfo
, item
, &ei_real_length_differs
);
2112 if ( dissector_try_heuristic(heur_epl_data_subdissector_list
, payload_tvb
, pinfo
, epl_tree
, &hdtbl_entry
, &msgType
))
2113 return offset
+ payload_len
;
2116 for (i
= 0; i
< maps_count
; i
++)
2118 proto_tree
*pdo_tree
;
2119 struct object_mapping
*map
= &mappings
[i
];
2120 unsigned willbe_offset_bits
= map
->bit_offset
+ map
->no_of_bits
;
2122 if (!(map
->frame
.first
< pinfo
->num
&& pinfo
->num
< map
->frame
.last
))
2125 if (willbe_offset_bits
> payload_len_bits
)
2128 item
= proto_tree_add_string_format(epl_tree
, hf_epl_pdo
, payload_tvb
, 0, 0, "", "%s", map
->title
);
2129 pdo_tree
= proto_item_add_subtree(item
, map
->ett
);
2131 item
= proto_tree_add_uint_format_value(pdo_tree
, hf_epl_pdo_index
, payload_tvb
, 0, 0, map
->pdo
.idx
, "%04X", map
->pdo
.idx
);
2132 proto_item_set_generated(item
);
2134 proto_item_append_text (item
, " (%s)", map
->index_name
);
2136 item
= proto_tree_add_uint_format_value(pdo_tree
, hf_epl_pdo_subindex
, payload_tvb
, 0, 0, map
->pdo
.subindex
, "%02X", map
->pdo
.subindex
);
2137 proto_item_set_generated(item
);
2139 if (map
->info
&& map
->info
->name
!= map
->index_name
)
2140 proto_item_append_text (item
, " (%s)", map
->info
->name
);
2142 if (show_pdo_meta_info
)
2144 proto_tree
*meta_tree
;
2145 proto_item
*meta_item
= proto_tree_add_item(pdo_tree
, hf_epl_od_meta
, tvb
, offset
, 0, ENC_NA
);
2146 meta_tree
= proto_item_add_subtree(meta_item
, ett_epl_pdo_meta
);
2148 proto_tree_add_uint(meta_tree
, hf_epl_od_meta_mapping_index
, tvb
, 0, 0, map
->param
.idx
);
2149 proto_tree_add_uint(meta_tree
, hf_epl_od_meta_mapping_subindex
, tvb
, 0, 0, map
->param
.subindex
);
2150 proto_tree_add_uint(meta_tree
, hf_epl_od_meta_lifetime_start
, tvb
, 0, 0, map
->frame
.first
);
2152 if (map
->frame
.last
!= UINT32_MAX
)
2153 proto_tree_add_uint(meta_tree
, hf_epl_od_meta_lifetime_end
, tvb
, 0, 0, map
->frame
.last
);
2155 item
= proto_tree_add_uint(meta_tree
, hf_epl_od_meta_offset
, tvb
, 0, 0, map
->bit_offset
);
2156 proto_item_append_text (item
, " bits");
2157 item
= proto_tree_add_uint(meta_tree
, hf_epl_od_meta_length
, tvb
, 0, 0, map
->no_of_bits
);
2158 proto_item_append_text (item
, " bits");
2161 proto_item_set_generated(meta_item
);
2164 dissect_epl_payload(
2166 tvb_new_octet_aligned(payload_tvb
, map
->bit_offset
, map
->no_of_bits
),
2167 pinfo
, 0, map
->no_of_bits
/ 8, map
->info
? map
->info
->type
: NULL
, msgType
2170 payload_len
-= map
->no_of_bits
/ 8;
2172 off
= willbe_offset_bits
/ 8;
2175 /* If we don't have more information, resort to data dissector */
2176 if (tvb_captured_length_remaining(payload_tvb
, off
))
2178 return dissect_epl_payload(epl_tree
, payload_tvb
, pinfo
, off
, payload_len
, NULL
, msgType
);
2180 return offset
+ payload_len
;
2183 static uint8_t epl_placeholder_mac_addr
[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2184 static address epl_placeholder_mac
= ADDRESS_INIT(AT_ETHER
, 6, epl_placeholder_mac_addr
);
2186 static struct epl_convo
*
2187 epl_get_convo(packet_info
*pinfo
, int opts
)
2189 struct epl_convo
*convo
;
2190 conversation_t
* epan_convo
;
2192 address
*node_addr
= &epl_placeholder_mac
;
2193 address
*node_dl_addr
= &epl_placeholder_mac
;
2195 if (opts
& CONVO_FOR_REQUEST
)
2197 node_port
= pinfo
->destport
;
2200 if (pinfo
->dst
.type
== AT_IPv4
|| pinfo
->dst
.type
== AT_ETHER
)
2201 node_addr
= &pinfo
->dst
;
2203 if (pinfo
->dl_dst
.type
== AT_ETHER
)
2204 node_dl_addr
= &pinfo
->dl_dst
;
2208 node_port
= pinfo
->srcport
;
2211 if (pinfo
->src
.type
== AT_IPv4
|| pinfo
->src
.type
== AT_ETHER
)
2212 node_addr
= &pinfo
->src
;
2214 if (pinfo
->dl_src
.type
== AT_ETHER
)
2215 node_dl_addr
= &pinfo
->dl_src
;
2217 /* It'd be better to consult the Ethernet or IP address when matching conversations,
2218 * but an ASnd request is targeted at a Multicast MAC address, so we'll use
2219 * a constant address for lookup
2220 * TODO: If you, the reader, figure out a way to lookup a conversation by port only
2221 * remove the following assignment
2223 node_addr
= &epl_placeholder_mac
;
2225 if ((epan_convo
= find_conversation(pinfo
->num
, node_addr
, node_addr
,
2226 conversation_pt_to_conversation_type(pinfo
->ptype
), node_port
, node_port
, NO_ADDR_B
|NO_PORT_B
)))
2228 /* XXX Do I need to check setup_frame != pinfo->num in order to not
2229 * create unnecessary new conversations?
2230 * if not, move the CONVO_ALWAYS_CREATE check up into the if and drop
2233 if ((opts
& CONVO_ALWAYS_CREATE
) && epan_convo
->setup_frame
!= pinfo
->num
)
2234 goto new_convo_creation
;
2236 if (pinfo
->num
> epan_convo
->last_frame
)
2237 epan_convo
->last_frame
= pinfo
->num
;
2242 epan_convo
= conversation_new(pinfo
->num
, node_addr
, node_addr
,
2243 conversation_pt_to_conversation_type(pinfo
->ptype
), node_port
, node_port
, NO_ADDR2
|NO_PORT2
);
2246 convo
= (struct epl_convo
*)conversation_get_proto_data(epan_convo
, proto_epl
);
2250 convo
= wmem_new0(wmem_file_scope(), struct epl_convo
);
2251 convo
->CN
= (uint8_t)node_port
;
2253 convo
->generation
= current_convo_generation
; /* FIXME remove */
2254 convo
->TPDO
= wmem_array_new(pdo_mapping_scope
, sizeof (struct object_mapping
));
2255 convo
->RPDO
= wmem_array_new(pdo_mapping_scope
, sizeof (struct object_mapping
));
2257 convo
->profile
= (struct profile
*)wmem_map_lookup(epl_profiles_by_address
, node_dl_addr
);
2258 if (!convo
->profile
)
2259 convo
->profile
= (struct profile
*)wmem_map_lookup(epl_profiles_by_nodeid
, GUINT_TO_POINTER(convo
->CN
));
2261 if (!convo
->profile
)
2262 convo
->profile
= epl_default_profile
;
2264 convo
->seq_send
= 0x00;
2265 conversation_add_proto_data(epan_convo
, proto_epl
, (void *)convo
);
2268 if (convo
->generation
!= current_convo_generation
)
2269 { /* FIXME remove */
2270 convo
->TPDO
= wmem_array_new(pdo_mapping_scope
, sizeof (struct object_mapping
));
2271 convo
->RPDO
= wmem_array_new(pdo_mapping_scope
, sizeof (struct object_mapping
));
2272 convo
->generation
= current_convo_generation
;
2280 epl_update_convo_cn_profile(struct epl_convo
*convo
)
2282 struct profile
*candidate
; /* Best matching profile */
2283 if ((candidate
= (struct profile
*)wmem_map_lookup(epl_profiles_by_device
, GUINT_TO_POINTER(convo
->device_type
))))
2285 struct profile
*iter
= candidate
;
2287 if ((iter
->vendor_id
== 0 && convo
->product_code
== 0 && !candidate
->vendor_id
)
2288 || (iter
->vendor_id
== convo
->vendor_id
&& !candidate
->product_code
)
2289 || (iter
->vendor_id
== convo
->vendor_id
&& iter
->product_code
== convo
->product_code
))
2294 } while ((iter
= iter
->next
));
2297 convo
->profile
= candidate
;
2299 if (!wmem_array_get_count(convo
->RPDO
))
2301 wmem_array_append(convo
->RPDO
,
2302 wmem_array_get_raw(candidate
->RPDO
),
2303 wmem_array_get_count(candidate
->RPDO
)
2306 if (!wmem_array_get_count(convo
->TPDO
))
2308 wmem_array_append(convo
->TPDO
,
2309 wmem_array_get_raw(candidate
->TPDO
),
2310 wmem_array_get_count(candidate
->TPDO
)
2318 static struct object
*
2319 object_lookup(struct profile
*profile
, uint16_t idx
)
2321 if (profile
== NULL
)
2324 return (struct object
*)wmem_map_lookup(profile
->objects
, GUINT_TO_POINTER(idx
));
2327 static const struct subobject
*
2328 subobject_lookup(struct object
*obj
, uint8_t subindex
)
2330 if (!obj
|| !obj
->subindices
) return NULL
;
2331 return (const struct subobject
*)epl_wmem_iarray_find(obj
->subindices
, subindex
);
2334 /* epl duplication table hash function */
2336 epl_duplication_hash(const void *k
)
2338 const duplication_key
*key
= (const duplication_key
*)k
;
2341 hash
= ((key
->src
)<<24) | ((key
->dest
)<<16)|
2342 ((key
->seq_recv
)<<8)|(key
->seq_send
);
2347 /* epl duplication table equal function */
2349 epl_duplication_equal(const void *k1
, const void *k2
)
2351 const duplication_key
*key1
= (const duplication_key
*)k1
;
2352 const duplication_key
*key2
= (const duplication_key
*)k2
;
2355 hash
= (key1
->src
== key2
->src
)&&(key1
->dest
== key2
->dest
)&&
2356 (key1
->seq_recv
== key2
->seq_recv
)&&(key1
->seq_send
== key2
->seq_send
);
2361 /* free the permanent key */
2365 duplication_key
*key
= (duplication_key
*)ptr
;
2366 g_slice_free(duplication_key
, key
);
2369 /* removes the table entries of a specific transfer */
2371 epl_duplication_remove(GHashTable
* table
, uint8_t src
, uint8_t dest
)
2373 GHashTableIter iter
;
2375 duplication_key
*key
;
2377 g_hash_table_iter_init(&iter
, table
);
2379 while(g_hash_table_iter_next(&iter
, &pkey
, NULL
))
2381 key
= (duplication_key
*)pkey
;
2383 if((src
== key
->src
) && (dest
== key
->dest
))
2385 /* remove the key + value from the hash table */
2386 g_hash_table_iter_remove(&iter
);
2391 /* insert function */
2393 epl_duplication_insert(GHashTable
* table
, void *ptr
, uint32_t frame
)
2395 duplication_data
*data
= NULL
;
2396 duplication_key
*key
= NULL
;
2399 /* check if the values are stored */
2400 if(g_hash_table_lookup_extended(table
, ptr
, NULL
, &pdata
))
2402 data
= (duplication_data
*)pdata
;
2403 data
->frame
= frame
;
2405 /* insert the data struct into the table */
2408 key
= (duplication_key
*)wmem_memdup(wmem_file_scope(), ptr
,sizeof(duplication_key
));
2410 data
= wmem_new0(wmem_file_scope(), duplication_data
);
2411 data
->frame
= frame
;
2412 g_hash_table_insert(table
,(void *)key
, data
);
2418 epl_duplication_key(uint8_t src
, uint8_t dest
, uint8_t seq_recv
, uint8_t seq_send
)
2420 duplication_key
*key
= g_slice_new(duplication_key
);
2424 key
->seq_recv
= seq_recv
;
2425 key
->seq_send
= seq_send
;
2430 /* get the saved data */
2432 epl_duplication_get(GHashTable
* table
, void *ptr
)
2434 duplication_data
*data
= NULL
;
2437 if(g_hash_table_lookup_extended(table
, ptr
, NULL
, &pdata
))
2439 data
= (duplication_data
*)pdata
;
2440 if(data
->frame
== 0x00)
2450 setup_dissector(void)
2452 /* init duplication hash table */
2453 epl_duplication_table
= g_hash_table_new(epl_duplication_hash
, epl_duplication_equal
);
2455 /* create memory block for upload/download */
2456 memset(&epl_asnd_sdo_reassembly_write
, 0, sizeof(epl_sdo_reassembly
));
2457 memset(&epl_asnd_sdo_reassembly_read
, 0, sizeof(epl_sdo_reassembly
));
2459 /* free object mappings in one swoop */
2460 pdo_mapping_scope
= wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE
);
2464 cleanup_dissector(void)
2466 wmem_destroy_allocator(pdo_mapping_scope
);
2467 pdo_mapping_scope
= NULL
;
2469 g_hash_table_destroy(epl_duplication_table
);
2476 /* preference whether or not display the SoC flags in info column */
2477 bool show_soc_flags
;
2479 /* Define the tap for epl */
2480 /*static int epl_tap = -1;*/
2483 epl_get_sequence_nr(packet_info
*pinfo
)
2485 uint16_t seqnum
= 0x00;
2488 if ( ( data
= p_get_proto_data ( wmem_file_scope(), pinfo
, proto_epl
, ETHERTYPE_EPL_V2
) ) == NULL
)
2489 p_add_proto_data ( wmem_file_scope(), pinfo
, proto_epl
, ETHERTYPE_EPL_V2
, GUINT_TO_POINTER((unsigned)seqnum
) );
2491 seqnum
= GPOINTER_TO_UINT(data
);
2497 epl_set_sequence_nr(packet_info
*pinfo
, uint16_t seqnum
)
2499 if ( p_get_proto_data ( wmem_file_scope(), pinfo
, proto_epl
, ETHERTYPE_EPL_V2
) != NULL
)
2500 p_remove_proto_data( wmem_file_scope(), pinfo
, proto_epl
, ETHERTYPE_EPL_V2
);
2502 p_add_proto_data ( wmem_file_scope(), pinfo
, proto_epl
, ETHERTYPE_EPL_V2
, GUINT_TO_POINTER((unsigned)seqnum
) );
2506 elp_version( char *result
, uint32_t version
)
2508 snprintf( result
, ITEM_LABEL_LENGTH
, "%d.%d", hi_nibble(version
), lo_nibble(version
));
2510 /* Code to actually dissect the packets */
2512 dissect_eplpdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, bool udpencap
)
2515 const char *src_str
, *dest_str
;
2516 /* static epl_info_t mi; */
2517 /* Set up structures needed to add the protocol subtree and manage it */
2519 proto_tree
*epl_tree
= NULL
, *epl_src_item
, *epl_dest_item
;
2520 int offset
= 0, size
= 0;
2521 heur_dtbl_entry_t
*hdtbl_entry
;
2522 struct epl_convo
*convo
;
2523 proto_item
*msg_typ_hidden
= NULL
;
2525 if (tvb_reported_length(tvb
) < 3)
2527 /* Not enough data for an EPL header; don't try to interpret it */
2531 /* Get message type */
2532 epl_mtyp
= tvb_get_uint8(tvb
, EPL_MTYP_OFFSET
) & 0x7F;
2535 * In case the packet is a protocol encoded in the basic EPL transport stream,
2536 * give that protocol a chance to make a heuristic dissection, before we continue
2537 * to dissect it as a normal EPL packet.
2539 if (dissector_try_heuristic(heur_epl_subdissector_list
, tvb
, pinfo
, tree
, &hdtbl_entry
, &epl_mtyp
))
2540 return tvb_reported_length(tvb
);
2542 if (!try_val_to_str(epl_mtyp
, mtyp_vals
)) {
2543 /* Not an EPL packet */
2547 /* Make entries in Protocol column and Info column on summary display */
2548 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, udpencap
? "POWERLINK/UDP" : "POWERLINK");
2551 /* mi.epl_mtyp = epl_mtyp;
2552 tap_queue_packet(epl_tap, pinfo, &mi);
2555 /* IP addresses are always in 192.168.100.0/24
2556 * with last octet being the node id
2557 * The original src/dest node ids are reserved
2560 pinfo
->ptype
= PT_NONE
;
2562 /* Get Destination and Source */
2565 /* The dissector may be invoked without an IP layer,
2566 * so we need to check we can actually index into the buffer
2568 if (pinfo
->net_dst
.type
== AT_IPv4
)
2569 pinfo
->destport
= ((const uint8_t*)pinfo
->net_dst
.data
)[3];
2570 if (pinfo
->net_src
.type
== AT_IPv4
)
2571 pinfo
->srcport
= ((const uint8_t*)pinfo
->net_src
.data
)[3];
2575 pinfo
->destport
= tvb_get_uint8(tvb
, EPL_DEST_OFFSET
);
2576 pinfo
->srcport
= tvb_get_uint8(tvb
, EPL_SRC_OFFSET
);
2579 epl_segmentation
.dest
= pinfo
->destport
;
2580 dest_str
= decode_epl_address(pinfo
->destport
);
2582 epl_segmentation
.src
= pinfo
->srcport
;
2583 src_str
= decode_epl_address(pinfo
->srcport
);
2585 col_clear(pinfo
->cinfo
, COL_INFO
);
2587 /* Choose the right string for "Info" column (message type) */
2591 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d SoC ", pinfo
->srcport
, pinfo
->destport
);
2595 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d PReq ", pinfo
->srcport
, pinfo
->destport
);
2599 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d PRes ", pinfo
->srcport
, pinfo
->destport
);
2603 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d SoA ", pinfo
->srcport
, pinfo
->destport
);
2607 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d ASnd ", pinfo
->srcport
, pinfo
->destport
);
2611 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d AInv ", pinfo
->srcport
, pinfo
->destport
);
2615 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%3d->%3d AMNI ", pinfo
->srcport
, pinfo
->destport
);
2618 default: /* no valid EPL packet */
2624 /* create display subtree for the protocol */
2625 ti
= proto_tree_add_item(tree
, proto_epl
, tvb
, 0, -1, ENC_NA
);
2626 epl_tree
= proto_item_add_subtree(ti
, ett_epl
);
2628 /* create a hidden field for filtering all EPL message types with simple syntax (epl.soc, epl.soa,...) */
2632 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_soc
, tvb
, offset
, 1, epl_mtyp
);
2636 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_preq
, tvb
, offset
, 1, epl_mtyp
);
2640 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_pres
, tvb
, offset
, 1, epl_mtyp
);
2644 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_soa
, tvb
, offset
, 1, epl_mtyp
);
2648 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_asnd
, tvb
, offset
, 1, epl_mtyp
);
2652 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_amni
, tvb
, offset
, 1, epl_mtyp
);
2656 msg_typ_hidden
= proto_tree_add_boolean(epl_tree
, hf_epl_ainv
, tvb
, offset
, 1, epl_mtyp
);
2659 proto_item_set_hidden(msg_typ_hidden
);
2661 proto_tree_add_item(epl_tree
,
2662 hf_epl_mtyp
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2666 if (tree
&& !udpencap
)
2668 epl_dest_item
= proto_tree_add_item(epl_tree
, hf_epl_node
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2669 proto_item_set_hidden(epl_dest_item
);
2670 epl_dest_item
= proto_tree_add_item(epl_tree
, hf_epl_dest
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2671 proto_item_append_text (epl_dest_item
, "%s", dest_str
);
2674 epl_src_item
= proto_tree_add_item(epl_tree
, hf_epl_node
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2675 proto_item_set_hidden(epl_src_item
);
2676 epl_src_item
= proto_tree_add_item(epl_tree
, hf_epl_src
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2677 proto_item_append_text (epl_src_item
, "%s", src_str
);
2685 /* The rest of the EPL dissector depends on the message type */
2689 offset
= dissect_epl_soc(epl_tree
, tvb
, pinfo
, offset
);
2693 convo
= epl_get_convo(pinfo
, CONVO_FOR_REQUEST
);
2694 offset
= dissect_epl_preq(convo
, epl_tree
, tvb
, pinfo
, offset
);
2698 convo
= epl_get_convo(pinfo
, CONVO_FOR_RESPONSE
);
2699 offset
= dissect_epl_pres(convo
, epl_tree
, tvb
, pinfo
, offset
);
2703 offset
= dissect_epl_soa(epl_tree
, tvb
, pinfo
, offset
);
2707 offset
= dissect_epl_asnd(epl_tree
, tvb
, pinfo
, offset
);
2711 offset
= dissect_epl_ainv(epl_tree
, tvb
, pinfo
, offset
);
2715 /* Currently all fields in the AMNI frame are reserved. Therefore
2716 * there's nothing to dissect! Everything is given to the heuristic,
2717 * which will dissect as data, if no heuristic dissector uses it. */
2718 size
= tvb_captured_length_remaining(tvb
, offset
);
2719 offset
= dissect_epl_payload(epl_tree
, tvb
, pinfo
, offset
, size
, NULL
, EPL_AMNI
);
2722 /* Switch cases are exhaustive. Default case never occurs */
2730 dissect_epl(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
2732 return dissect_eplpdu(tvb
, pinfo
, tree
, false);
2736 dissect_epludp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
2738 return dissect_eplpdu(tvb
, pinfo
, tree
, true);
2743 decode_epl_address (unsigned char adr
)
2745 const char *addr_str
;
2747 addr_str
= try_val_to_str(adr
, addr_str_vals
);
2749 if (addr_str
!= NULL
)
2755 if (EPL_IS_CN_NODEID(adr
))
2761 return addr_str_res
;
2767 dissect_epl_payload(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, int len
, const struct epl_datatype
*type
, uint8_t msgType
)
2769 int rem_len
= 0, payload_len
= 0;
2770 tvbuff_t
*payload_tvb
= NULL
;
2771 heur_dtbl_entry_t
*hdtbl_entry
= NULL
;
2772 proto_item
*item
= NULL
;
2777 rem_len
= tvb_captured_length_remaining(tvb
, offset
);
2778 payload_tvb
= tvb_new_subset_length(tvb
, offset
, MIN(len
, rem_len
));
2779 payload_len
= tvb_captured_length_remaining(payload_tvb
, 0);
2781 if ( payload_len
< len
)
2783 item
= proto_tree_add_uint(epl_tree
, hf_epl_payload_real
, tvb
, offset
, payload_len
, payload_len
);
2784 proto_item_set_generated(item
);
2785 expert_add_info(pinfo
, item
, &ei_real_length_differs
);
2788 /* To satisfy heurstic dissectors, we need to pass then the whole PDO payload as-is,
2789 * so we check whether we were called from dissect_epl_pdo and skip trying heuristic
2790 * dissectors for the PDO's components
2792 if (msgType
!= EPL_PREQ
&& msgType
!= EPL_PRES
)
2794 if ( dissector_try_heuristic(heur_epl_data_subdissector_list
, payload_tvb
, pinfo
, epl_tree
, &hdtbl_entry
, &msgType
))
2795 return offset
+ payload_len
;
2798 if (type
&& (!type
->len
|| type
->len
== payload_len
))
2800 if (*type
->hf
!= hf_epl_od_uint
)
2802 proto_tree_add_item(epl_tree
, *type
->hf
, tvb
, offset
, type
->len
, type
->encoding
);
2806 /* proto_tree_add_item would zero-pad our hex representation
2807 * to full 64 bit, which looks kind of ugly, so we add the
2808 * HEX part of BASE_DEC_HEX ourselves
2811 item
= proto_tree_add_item_ret_uint64(epl_tree
, *type
->hf
,
2812 tvb
, offset
, type
->len
, type
->encoding
, &val
);
2813 proto_item_append_text(item
, " (0x%.*" PRIx64
")", 2*type
->len
, val
);
2816 /* If a mapping uses a type of fixed width that's not equal to
2817 * the function argument's length, fallback to raw data dissector
2821 /* We don't know the type, so let's use appropriate unsignedX */
2822 if (payload_len
< (int)sizeof (uint64_t) && interpret_untyped_as_le
)
2825 item
= proto_tree_add_item_ret_uint64(epl_tree
, hf_epl_od_uint
,
2826 payload_tvb
, 0, payload_len
, ENC_LITTLE_ENDIAN
, &val
);
2827 proto_item_append_text(item
, " (0x%.*" PRIx64
")", 2*payload_len
, val
);
2831 call_data_dissector(payload_tvb
, pinfo
, epl_tree
);
2835 return offset
+ payload_len
;
2839 dissect_epl_soc(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
2842 static int * const soc_flags
[] = {
2851 flags
= tvb_get_uint8(tvb
, offset
);
2852 proto_tree_add_bitmask(epl_tree
, tvb
, offset
, hf_epl_soc_flags
, ett_epl_soc
, soc_flags
, ENC_NA
);
2858 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "F:MC=%d,PS=%d",
2859 ((EPL_SOC_MC_MASK
& flags
) >> 7), ((EPL_SOC_PS_MASK
& flags
) >> 6));
2862 proto_tree_add_item(epl_tree
, hf_epl_soc_nettime
, tvb
, offset
, 8, ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
);
2865 proto_tree_add_item(epl_tree
, hf_epl_soc_relativetime
, tvb
, offset
, 8, ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
);
2874 dissect_epl_preq(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
2879 static int * const req_flags
[] = {
2888 flags
= tvb_get_uint8(tvb
, offset
);
2889 proto_tree_add_bitmask(epl_tree
, tvb
, offset
, hf_epl_preq_flags
, ett_epl_preq
, req_flags
, ENC_NA
);
2892 /* dissect 2nd flag field */
2893 proto_tree_add_item(epl_tree
, hf_epl_preq_fls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2894 proto_tree_add_item(epl_tree
, hf_epl_preq_sls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2897 pdoversion
= tvb_get_uint8(tvb
, offset
);
2898 proto_tree_add_item(epl_tree
, hf_epl_preq_pdov
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2901 /* get size of payload */
2902 len
= tvb_get_letohs(tvb
, offset
);
2903 proto_tree_add_uint(epl_tree
, hf_epl_preq_size
, tvb
, offset
, 2, len
);
2905 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%4d] F:RD=%d,EA=%d V:%d.%d", len
,
2906 ((EPL_PDO_RD_MASK
& flags
) >> 0), ((EPL_PDO_EA_MASK
& flags
) >> 2), hi_nibble(pdoversion
), lo_nibble(pdoversion
));
2909 offset
= dissect_epl_pdo(convo
, epl_tree
, tvb
, pinfo
, offset
, len
, EPL_PREQ
);
2917 dissect_epl_pres(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
2921 uint8_t state
, flags
, flags2
;
2922 static int * const res_flags
[] = {
2929 state
= tvb_get_uint8(tvb
, offset
);
2930 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if the sender is CN or MN */
2932 proto_tree_add_item(epl_tree
, hf_epl_pres_stat_cs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2936 proto_tree_add_item(epl_tree
, hf_epl_pres_stat_ms
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2940 flags
= tvb_get_uint8(tvb
, offset
);
2941 proto_tree_add_bitmask(epl_tree
, tvb
, offset
, hf_epl_pres_flags
, ett_epl_pres
, res_flags
, ENC_NA
);
2944 flags2
= tvb_get_uint8(tvb
, offset
);
2946 proto_tree_add_item(epl_tree
, hf_epl_pres_fls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2947 proto_tree_add_item(epl_tree
, hf_epl_pres_sls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2948 proto_tree_add_item(epl_tree
, hf_epl_pres_pr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2949 proto_tree_add_item(epl_tree
, hf_epl_pres_rs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2952 pdoversion
= tvb_get_uint8(tvb
, offset
);
2953 proto_tree_add_item(epl_tree
, hf_epl_pres_pdov
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2956 /* get size of payload */
2957 len
= tvb_get_letohs(tvb
, offset
);
2958 proto_tree_add_uint(epl_tree
, hf_epl_pres_size
, tvb
, offset
, 2, len
);
2960 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%4d]", len
);
2962 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " F:RD=%d,EN=%d,RS=%d,PR=%d V=%d.%d",
2963 ((EPL_PDO_RD_MASK
& flags
) >> 0), ((EPL_PDO_EN_MASK
& flags
) >> 4), (EPL_PDO_RS_MASK
& flags2
), (EPL_PDO_PR_MASK
& flags2
) >> 3,
2964 hi_nibble(pdoversion
), lo_nibble(pdoversion
));
2966 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if the sender is CN or MN */
2968 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s",
2969 val_to_str(state
, epl_nmt_cs_vals
, "Unknown(%d)"));
2973 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s",
2974 val_to_str(state
, epl_nmt_ms_vals
, "Unknown(%d)"));
2979 offset
= dissect_epl_pdo(convo
, epl_tree
, tvb
, pinfo
, offset
, len
, EPL_PRES
);
2986 dissect_epl_soa(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
2988 uint8_t svid
, target
;
2989 uint8_t state
, flags
;
2990 proto_item
*psf_item
= NULL
;
2991 proto_tree
*psf_tree
= NULL
;
2993 state
= tvb_get_uint8(tvb
, offset
);
2994 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if CN or MN */
2996 proto_tree_add_item(epl_tree
, hf_epl_soa_stat_cs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3000 proto_tree_add_item(epl_tree
, hf_epl_soa_stat_ms
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3005 flags
= tvb_get_uint8(tvb
, offset
);
3006 svid
= tvb_get_uint8(tvb
, offset
+ 2);
3007 if (svid
== EPL_SOA_IDENTREQUEST
)
3009 proto_tree_add_item(epl_tree
, hf_epl_soa_dna_an_lcl
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3011 proto_tree_add_item(epl_tree
, hf_epl_soa_dna_an_glb
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3012 proto_tree_add_item(epl_tree
, hf_epl_soa_ea
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3013 proto_tree_add_item(epl_tree
, hf_epl_soa_er
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3016 proto_tree_add_uint(epl_tree
, hf_epl_soa_svid
, tvb
, offset
, 1, svid
);
3019 target
= tvb_get_uint8(tvb
, offset
);
3020 proto_tree_add_uint(epl_tree
, hf_epl_soa_svtg
, tvb
, offset
, 1, target
);
3023 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%s)->%3d",
3024 rval_to_str_const(svid
, soa_svid_id_vals
, "Unknown"), target
);
3026 /* append info entry with flag information */
3027 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " F:EA=%d,ER=%d ",
3028 ((EPL_SOA_EA_MASK
& flags
) >> 2), ((EPL_SOA_ER_MASK
& flags
) >> 1));
3030 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if CN or MN */
3032 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s",
3033 val_to_str(state
, epl_nmt_cs_vals
, "Unknown(%d)"));
3037 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s",
3038 val_to_str(state
, epl_nmt_ms_vals
, "Unknown(%d)"));
3041 proto_tree_add_item(epl_tree
, hf_epl_soa_eplv
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3044 /* decode redundancy flags */
3045 proto_tree_add_item(epl_tree
, hf_epl_soa_rrflags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3046 proto_tree_add_item(epl_tree
, hf_epl_soa_rrflags_ringstat
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3047 proto_tree_add_item(epl_tree
, hf_epl_soa_rrflags_ringred
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3048 proto_tree_add_item(epl_tree
, hf_epl_soa_rrflags_cblred
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3049 proto_tree_add_item(epl_tree
, hf_epl_soa_rrflags_mnred
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3052 if (svid
== EPL_SOA_SYNCREQUEST
)
3054 /* SyncControl bit0-7 */
3055 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_soa_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3056 proto_item_append_text(psf_item
, " (Bits 0..7)");
3057 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_soa_sync
);
3058 proto_tree_add_item(psf_tree
, hf_epl_soa_mac
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3059 proto_tree_add_item(psf_tree
, hf_epl_soa_pre_tm
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3060 proto_tree_add_item(psf_tree
, hf_epl_soa_mnd_sec
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3061 proto_tree_add_item(psf_tree
, hf_epl_soa_mnd_fst
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3062 proto_tree_add_item(psf_tree
, hf_epl_soa_pre_sec
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3063 proto_tree_add_item(psf_tree
, hf_epl_soa_pre_fst
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3065 /* SyncControl 2 - reserved */
3066 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_soa_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3067 proto_item_append_text(psf_item
, " (Bits 8..15)");
3069 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_soa_sync
);
3072 /* SyncControl 3 - reserved */
3073 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_soa_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3074 proto_item_append_text(psf_item
, " (Bits 16..23)");
3076 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_soa_sync
);
3080 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_soa_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3081 proto_item_append_text(psf_item
, " (Bits 24..31)");
3082 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_soa_sync
);
3083 proto_tree_add_item(psf_tree
, hf_epl_soa_pre_set
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3084 proto_tree_add_item(psf_tree
, hf_epl_soa_pre_res
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3087 proto_tree_add_item(epl_tree
, hf_epl_soa_pre_fst_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3089 /* PResTimeSecond */
3090 proto_tree_add_item(epl_tree
, hf_epl_soa_pre_sec_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3092 /* SyncMNDelayFirst */
3093 proto_tree_add_item(epl_tree
, hf_epl_soa_mnd_fst_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3095 /* SyncMNDelaySecond */
3096 proto_tree_add_item(epl_tree
, hf_epl_soa_mnd_sec_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3098 /* PResFallBackTimeout */
3099 proto_tree_add_item(epl_tree
, hf_epl_soa_pre_tm_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3101 /* DestMacAddress */
3102 proto_tree_add_item(epl_tree
, hf_epl_soa_mac_end
, tvb
, offset
, 6, ENC_NA
);
3112 dissect_epl_asnd(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3115 uint8_t flags
, flags2
;
3116 int size
, reported_len
;
3119 proto_tree
*subtree
;
3120 struct epl_convo
*convo
;
3122 /* get ServiceID of payload */
3123 svid
= tvb_get_uint8(tvb
, offset
);
3124 item
= proto_tree_add_uint(epl_tree
, hf_epl_asnd_svid
, tvb
, offset
, 1, svid
);
3128 flags
= tvb_get_uint8(tvb
, offset
);
3129 flags2
= tvb_get_uint8(tvb
, offset
+ 1);
3131 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%s) ",
3132 rval_to_str_const(svid
, asnd_svid_id_vals
, "Unknown"));
3134 /* append info entry with flag information for sres/ires frames */
3135 if ((svid
== EPL_ASND_IDENTRESPONSE
) || (svid
== EPL_ASND_STATUSRESPONSE
))
3137 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " F:EC=%d,EN=%d,RS=%d,PR=%d ",
3138 ((EPL_ASND_EC_MASK
& flags
) >> 3), ((EPL_ASND_EN_MASK
& flags
) >> 4), (EPL_ASND_RS_MASK
& flags2
), (EPL_ASND_PR_MASK
& flags2
) >> 3);
3144 case EPL_ASND_IDENTRESPONSE
:
3145 convo
= epl_get_convo(pinfo
, CONVO_FOR_RESPONSE
);
3146 offset
= dissect_epl_asnd_ires(convo
, epl_tree
, tvb
, pinfo
, offset
);
3149 case EPL_ASND_STATUSRESPONSE
:
3150 offset
= dissect_epl_asnd_sres(epl_tree
, tvb
, pinfo
, offset
);
3153 case EPL_ASND_NMTREQUEST
:
3154 offset
= dissect_epl_asnd_nmtreq(epl_tree
, tvb
, pinfo
, offset
);
3157 case EPL_ASND_NMTCOMMAND
:
3158 offset
= dissect_epl_asnd_nmtcmd(epl_tree
, tvb
, pinfo
, offset
);
3162 subtree
= proto_item_add_subtree ( item
, ett_epl_sdo
);
3163 offset
= dissect_epl_asnd_sdo(subtree
, tvb
, pinfo
, offset
);
3165 case EPL_ASND_SYNCRESPONSE
:
3166 offset
= dissect_epl_asnd_resp(epl_tree
, tvb
, pinfo
, offset
);
3169 size
= tvb_captured_length_remaining(tvb
, offset
);
3170 reported_len
= tvb_reported_length_remaining(tvb
, offset
);
3172 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, size
, reported_len
);
3173 /* Manufacturer specific entries for ASND services */
3174 if (svid
>= 0xA0 && svid
< 0xFF && dissector_try_uint(epl_asnd_dissector_table
,
3175 svid
, next_tvb
, pinfo
, ( epl_tree
? epl_tree
->parent
: NULL
))) {
3179 dissect_epl_payload(epl_tree
, tvb
, pinfo
, offset
, size
, NULL
, EPL_ASND
);
3186 dissect_epl_ainv(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3190 proto_tree
*subtree
;
3191 struct epl_convo
*convo
;
3193 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if CN or MN */
3195 proto_tree_add_item(epl_tree
, hf_epl_soa_stat_cs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3199 proto_tree_add_item(epl_tree
, hf_epl_soa_stat_ms
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3204 proto_tree_add_item(epl_tree
, hf_epl_soa_ea
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3205 proto_tree_add_item(epl_tree
, hf_epl_soa_er
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3208 svid
= tvb_get_uint8(tvb
, offset
);
3210 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%s) ", rval_to_str(svid
, asnd_svid_id_vals
, "UNKNOWN(%d)"));
3212 item
= proto_tree_add_uint(epl_tree
, hf_epl_asnd_svid
, tvb
, offset
, 1, svid
);
3217 case EPL_ASND_IDENTRESPONSE
:
3218 convo
= epl_get_convo(pinfo
, CONVO_FOR_RESPONSE
);
3219 offset
= dissect_epl_asnd_ires(convo
, epl_tree
, tvb
, pinfo
, offset
);
3222 case EPL_ASND_STATUSRESPONSE
:
3223 offset
= dissect_epl_asnd_sres(epl_tree
, tvb
, pinfo
, offset
);
3226 case EPL_ASND_NMTREQUEST
:
3227 offset
= dissect_epl_asnd_nmtreq(epl_tree
, tvb
, pinfo
, offset
);
3230 case EPL_ASND_NMTCOMMAND
:
3231 offset
= dissect_epl_asnd_nmtcmd(epl_tree
, tvb
, pinfo
, offset
);
3234 case EPL_SOA_UNSPECIFIEDINVITE
:
3235 proto_tree_add_item(epl_tree
, hf_epl_asnd_svtg
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3237 proto_tree_add_item(epl_tree
, hf_epl_soa_eplv
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3241 subtree
= proto_item_add_subtree ( item
, ett_epl_sdo
);
3242 offset
= dissect_epl_asnd_sdo(subtree
, tvb
, pinfo
, offset
);
3251 dissect_epl_asnd_nmtreq(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3255 rcid
= tvb_get_uint8(tvb
, offset
);
3257 proto_tree_add_uint(epl_tree
, hf_epl_asnd_nmtrequest_rcid
, tvb
, offset
, 1, rcid
);
3258 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtrequest_rct
, tvb
, offset
+1, 1, ENC_LITTLE_ENDIAN
);
3259 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtrequest_rcd
, tvb
, offset
+2, -1, ENC_NA
);
3263 col_append_str(pinfo
->cinfo
, COL_INFO
,
3264 val_to_str_ext(rcid
, &asnd_cid_vals_ext
, "Unknown (%d)"));
3270 dissect_epl_asnd_nmtdna(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3273 proto_tree
*epl_dna_tree
;
3274 uint32_t curr_node_num
;
3275 uint32_t new_node_num
;
3276 uint32_t lease_time
;
3277 uint32_t lease_time_s
;
3279 static int * const dna_flags
[] = {
3280 &hf_epl_asnd_nmtcommand_nmtdna_ltv
,
3281 &hf_epl_asnd_nmtcommand_nmtdna_hpm
,
3282 &hf_epl_asnd_nmtcommand_nmtdna_nnn
,
3283 &hf_epl_asnd_nmtcommand_nmtdna_mac
,
3284 &hf_epl_asnd_nmtcommand_nmtdna_cnn
,
3288 ti_dna
= proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_nmtdna
, tvb
, offset
, EPL_SIZEOF_NMTCOMMAND_DNA
, ENC_NA
);
3289 epl_dna_tree
= proto_item_add_subtree(ti_dna
, ett_epl_feat
);
3291 proto_tree_add_bitmask(epl_dna_tree
, tvb
, offset
, hf_epl_asnd_nmtcommand_nmtdna_flags
, ett_epl_asnd_nmt_dna
, dna_flags
, ENC_NA
);
3294 proto_tree_add_item(epl_dna_tree
, hf_epl_asnd_nmtcommand_nmtdna_currmac
, tvb
, offset
, 6, ENC_NA
);
3297 /* 64-bit mask specifying which hub ports are active (1) or inactive (0) */
3298 proto_tree_add_item(epl_dna_tree
, hf_epl_asnd_nmtcommand_nmtdna_hubenmsk
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
3301 proto_tree_add_item_ret_uint(epl_dna_tree
, hf_epl_asnd_nmtcommand_nmtdna_currnn
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &curr_node_num
);
3304 proto_tree_add_item_ret_uint (epl_dna_tree
, hf_epl_asnd_nmtcommand_nmtdna_newnn
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &new_node_num
);
3307 lease_time
= tvb_get_uint32(tvb
, offset
, ENC_LITTLE_ENDIAN
);
3308 lease_time_s
= lease_time
/ 1000000; /* us->s */
3309 us
.nsecs
= (lease_time
- lease_time_s
* 1000000) * 1000; /* us->ns */
3310 us
.secs
= lease_time_s
;
3311 proto_tree_add_time(epl_dna_tree
, hf_epl_asnd_nmtcommand_nmtdna_leasetime
, tvb
, offset
, 4, &us
);
3314 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %4d -> %4d", curr_node_num
, new_node_num
);
3321 dissect_epl_asnd_nmtcmd(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3323 uint8_t epl_asnd_nmtcommand_cid
;
3326 epl_asnd_nmtcommand_cid
= tvb_get_uint8(tvb
, offset
);
3327 proto_tree_add_uint(epl_tree
, hf_epl_asnd_nmtcommand_cid
, tvb
, offset
, 1, epl_asnd_nmtcommand_cid
);
3330 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str_ext(epl_asnd_nmtcommand_cid
, &asnd_cid_vals_ext
, "Unknown(%d)"));
3332 switch (epl_asnd_nmtcommand_cid
)
3334 case EPL_ASND_NMTCOMMAND_NMTNETHOSTNAMESET
:
3335 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_nmtnethostnameset_hn
, tvb
, offset
, 32, ENC_NA
);
3339 case EPL_ASND_NMTCOMMAND_NMTFLUSHARPENTRY
:
3340 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_nmtflusharpentry_nid
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3344 case EPL_ASND_NMTCOMMAND_NMTPUBLISHTIME
:
3345 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_nmtpublishtime_dt
, tvb
, offset
, 6, ENC_NA
);
3349 case EPL_ASND_NMTCOMMAND_NMTDNA
:
3350 /* This byte is reserved for the other NMT commands but some flags are placed in it for DNA */
3352 offset
= dissect_epl_asnd_nmtdna(epl_tree
, tvb
, pinfo
, offset
);
3355 case EPL_ASND_NMTCOMMAND_NMTRESETNODE
:
3356 errorcode
= tvb_get_letohs(tvb
, offset
);
3359 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", val_to_str(errorcode
, errorcode_vals
, "Unknown Error(0x%04x"));
3360 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_resetnode_reason
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3363 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_cdat
, tvb
, offset
, -1, ENC_NA
);
3367 proto_tree_add_item(epl_tree
, hf_epl_asnd_nmtcommand_cdat
, tvb
, offset
, -1, ENC_NA
);
3376 dissect_epl_asnd_ires(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3378 uint32_t epl_asnd_identresponse_ipa
, epl_asnd_identresponse_snm
, epl_asnd_identresponse_gtw
;
3379 proto_item
*ti_feat
, *ti
;
3380 proto_tree
*epl_feat_tree
;
3381 uint16_t device_type
;
3382 const char *profile_name
= NULL
;
3383 uint32_t response_time
;
3385 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_en
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3386 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_ec
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3389 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_fls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3390 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_sls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3391 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_pr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3392 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_rs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3395 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if CN or MN */
3397 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_stat_cs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3401 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_stat_ms
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3405 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_ever
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3408 /* decode FeatureFlags */
3409 ti_feat
= proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_feat
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3410 epl_feat_tree
= proto_item_add_subtree(ti_feat
, ett_epl_feat
);
3411 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit0
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3412 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit1
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3413 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit2
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3414 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit3
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3415 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit4
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3416 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit5
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3417 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit6
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3418 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit7
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3419 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit8
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3420 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit9
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3421 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitA
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3422 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitB
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3423 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitC
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3424 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitD
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3425 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitE
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3426 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bitF
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3427 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit10
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3428 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit11
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3429 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit12
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3430 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit13
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3431 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit14
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3432 proto_tree_add_item(epl_feat_tree
, hf_epl_asnd_identresponse_feat_bit21
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3435 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_mtu
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3438 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_pis
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3441 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_pos
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3444 response_time
= tvb_get_letohl(tvb
, offset
);
3445 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_rst
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3448 device_type
= tvb_get_letohs(tvb
, offset
);
3450 if (device_type
!= convo
->device_type
)
3451 convo
= epl_get_convo(pinfo
, CONVO_FOR_RESPONSE
| CONVO_ALWAYS_CREATE
);
3453 convo
->response_time
= response_time
;
3454 convo
->device_type
= device_type
;
3456 ti
= proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_dt
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3458 if (!convo
->profile
|| !convo
->profile
->nodeid
)
3459 epl_update_convo_cn_profile(convo
);
3460 if (convo
->profile
&& convo
->profile
->name
)
3461 profile_name
= convo
->profile
->name
;
3463 profile_name
= val_to_str_const(convo
->device_type
, epl_device_profiles
, "Unknown Profile");
3465 proto_item_append_text(ti
, " (%s)", profile_name
);
3467 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_dt_add
, tvb
, offset
+2, 2, ENC_LITTLE_ENDIAN
);
3469 if (convo
->profile
&& convo
->profile
->path
)
3471 ti
= proto_tree_add_string(epl_tree
, hf_epl_asnd_identresponse_profile_path
, tvb
, offset
, 2, convo
->profile
->path
);
3472 proto_item_set_generated(ti
);
3477 convo
->vendor_id
= tvb_get_letohl(tvb
, offset
);
3478 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_vid
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3481 convo
->product_code
= tvb_get_letohl(tvb
, offset
);
3482 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_productcode
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3485 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_rno
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3488 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_sno
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3491 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_vex1
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
3494 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_vcd
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3497 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_vct
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3500 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_ad
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3503 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_at
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3506 epl_asnd_identresponse_ipa
= tvb_get_ntohl(tvb
, offset
);
3507 proto_tree_add_ipv4(epl_tree
, hf_epl_asnd_identresponse_ipa
, tvb
, offset
, 4, epl_asnd_identresponse_ipa
);
3510 epl_asnd_identresponse_snm
= tvb_get_ntohl(tvb
, offset
);
3511 proto_tree_add_ipv4(epl_tree
, hf_epl_asnd_identresponse_snm
, tvb
, offset
, 4, epl_asnd_identresponse_snm
);
3514 epl_asnd_identresponse_gtw
= tvb_get_ntohl(tvb
, offset
);
3515 proto_tree_add_ipv4(epl_tree
, hf_epl_asnd_identresponse_gtw
, tvb
, offset
, 4, epl_asnd_identresponse_gtw
);
3518 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_hn
, tvb
, offset
, 32, ENC_ASCII
);
3521 proto_tree_add_item(epl_tree
, hf_epl_asnd_identresponse_vex2
, tvb
, offset
, 48, ENC_NA
);
3524 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(convo
->device_type
, epl_device_profiles
, "Device Profile %d"));
3530 dissect_epl_asnd_resp(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
)
3532 proto_item
*psf_item
= NULL
;
3533 proto_tree
*psf_tree
= NULL
;
3535 /* reserved 2 byte*/
3537 /* SyncStatus bit 0 - 7 */
3538 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3539 proto_item_append_text(psf_item
, " (Bits 0..7)");
3540 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sync
);
3541 proto_tree_add_item(psf_tree
, hf_epl_asnd_syncResponse_sec_val
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3542 proto_tree_add_item(psf_tree
, hf_epl_asnd_syncResponse_fst_val
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3544 /* SyncStatus bit 8 - 15 reserved */
3545 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3546 proto_item_append_text(psf_item
, " (Bits 8..15)");
3548 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sync
);
3551 /* SyncStatus bit 16 - 23 reserved */
3552 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3553 proto_item_append_text(psf_item
, " (Bits 16..23)");
3555 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sync
);
3558 /* SyncStatus bit 24 - 31 reserved */
3559 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_sync
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3560 proto_item_append_text(psf_item
, " (Bits 24..31)");
3561 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sync
);
3562 proto_tree_add_item(psf_tree
, hf_epl_asnd_syncResponse_mode
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3565 proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_latency
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3567 /* SyncDelayStation */
3568 proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_node
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3571 proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_delay
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3574 proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_pre_fst
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3576 /* PResTimeSecond */
3577 proto_tree_add_item(epl_tree
, hf_epl_asnd_syncResponse_pre_sec
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3583 dissect_epl_asnd_sres(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3585 proto_item
*ti_el_entry
, *ti_el_entry_type
;
3586 proto_tree
*epl_seb_tree
, *epl_el_tree
, *epl_el_entry_tree
, *epl_el_entry_type_tree
;
3587 unsigned number_of_entries
, cnt
; /* used for dissection of ErrorCodeList */
3590 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_en
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3591 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_ec
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3594 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_fls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3595 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_sls
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3596 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_pr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3597 proto_tree_add_item(epl_tree
, hf_epl_asnd_statusresponse_rs
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3600 nmt_state
= tvb_get_uint8(tvb
, offset
);
3601 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", val_to_str(nmt_state
, epl_nmt_cs_vals
, "Unknown (%d)"));
3603 if (pinfo
->srcport
!= EPL_MN_NODEID
) /* check if CN or MN */
3605 proto_tree_add_uint(epl_tree
, hf_epl_asnd_statusresponse_stat_cs
, tvb
, offset
, 1, nmt_state
);
3609 proto_tree_add_uint(epl_tree
, hf_epl_asnd_statusresponse_stat_ms
, tvb
, offset
, 1, nmt_state
);
3613 /* Subtree for the static error bitfield */
3614 epl_seb_tree
= proto_tree_add_subtree(epl_tree
, tvb
, offset
, 8, ett_epl_seb
, NULL
, "StaticErrorBitfield");
3616 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit0
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3617 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit1
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3618 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit2
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3619 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit3
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3620 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit4
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3621 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit5
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3622 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit7
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3625 proto_tree_add_item(epl_seb_tree
, hf_epl_asnd_statusresponse_seb_devicespecific_err
, tvb
,offset
, 6, ENC_NA
);
3628 /* List of errors / events */
3629 /* get the number of entries in the error code list*/
3630 number_of_entries
= (tvb_reported_length(tvb
)-offset
)/20;
3632 epl_el_tree
= proto_tree_add_subtree_format(epl_tree
, tvb
, offset
, -1, ett_epl_el
, NULL
, "ErrorCodeList: %d entries", number_of_entries
);
3634 /*Dissect the whole Error List (display each entry)*/
3635 for (cnt
= 0; cnt
<number_of_entries
; cnt
++)
3637 epl_el_entry_tree
= proto_tree_add_subtree_format(epl_el_tree
, tvb
, offset
, 20, ett_epl_el_entry
, &ti_el_entry
, "Entry %d", cnt
+1);
3640 ti_el_entry_type
= proto_tree_add_item(ti_el_entry
,
3641 hf_epl_asnd_statusresponse_el_entry_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3643 epl_el_entry_type_tree
= proto_item_add_subtree(ti_el_entry_type
,
3644 ett_epl_el_entry_type
);
3646 proto_tree_add_item(epl_el_entry_type_tree
,
3647 hf_epl_asnd_statusresponse_el_entry_type_profile
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3649 proto_tree_add_item(epl_el_entry_type_tree
,
3650 hf_epl_asnd_statusresponse_el_entry_type_mode
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3652 proto_tree_add_item(epl_el_entry_type_tree
,
3653 hf_epl_asnd_statusresponse_el_entry_type_bit14
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3655 proto_tree_add_item(epl_el_entry_type_tree
,
3656 hf_epl_asnd_statusresponse_el_entry_type_bit15
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3659 proto_tree_add_item(epl_el_entry_tree
, hf_epl_asnd_statusresponse_el_entry_code
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3662 proto_tree_add_item(epl_el_entry_tree
, hf_epl_asnd_statusresponse_el_entry_time
, tvb
, offset
, 8, ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
);
3665 proto_tree_add_item(epl_el_entry_tree
, hf_epl_asnd_statusresponse_el_entry_add
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
3673 dissect_epl_asnd_sdo(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
3675 uint16_t seqnum
= 0x00;
3677 offset
= dissect_epl_sdo_sequence(epl_tree
, tvb
, pinfo
, offset
, &seq_read
);
3679 seqnum
= epl_get_sequence_nr(pinfo
);
3681 /* if a frame is duplicated don't show the command layer */
3682 if(seqnum
== 0x00 || show_cmd_layer_for_duplicated
== true )
3684 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
3686 offset
= dissect_epl_sdo_command(epl_tree
, tvb
, pinfo
, offset
, seq_read
);
3688 else col_append_str(pinfo
->cinfo
, COL_INFO
, "Empty CommandLayer");
3694 dissect_epl_sdo_sequence(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t* seq
)
3696 uint8_t seq_recv
= 0x00, seq_send
= 0x00, rcon
= 0x00, scon
= 0x00;
3697 uint32_t frame
= 0x00;
3698 proto_tree
*sod_seq_tree
;
3700 uint8_t duplication
= 0x00;
3702 uint32_t saved_frame
;
3703 uint16_t seqnum
= 0;
3706 seq_recv
= tvb_get_uint8(tvb
, offset
);
3708 rcon
= seq_recv
& EPL_ASND_SDO_SEQ_CON_MASK
;
3710 seq_recv
= seq_recv
>> EPL_ASND_SDO_SEQ_MASK
;
3711 epl_segmentation
.recv
= seq_recv
;
3713 seq_send
= tvb_get_uint8(tvb
, offset
+1);
3715 scon
= seq_send
& EPL_ASND_SDO_SEQ_CON_MASK
;
3717 seq_send
= seq_send
>> EPL_ASND_SDO_SEQ_MASK
;
3718 epl_segmentation
.send
= seq_send
;
3719 /* get the current frame-number */
3723 key
= epl_duplication_key(epl_segmentation
.src
,epl_segmentation
.dest
,seq_recv
,seq_send
);
3725 /* Get the saved data */
3726 saved_frame
= epl_duplication_get(epl_duplication_table
, key
);
3728 /* clear array at the start Sequence */
3729 if((rcon
< EPL_VALID
&& scon
< EPL_VALID
)
3730 ||(rcon
== EPL_VALID
&& scon
< EPL_VALID
)
3731 ||(rcon
< EPL_VALID
&& scon
== EPL_VALID
))
3733 /* remove all the keys of the specified src and dest address*/
3734 epl_duplication_remove(epl_duplication_table
,epl_segmentation
.src
,epl_segmentation
.dest
);
3735 /* There is no cmd layer */
3736 epl_set_sequence_nr(pinfo
, 0x02);
3738 /* if cooked/fuzzed capture*/
3739 else if(seq_recv
>= EPL_MAX_SEQUENCE
|| seq_send
>= EPL_MAX_SEQUENCE
3740 ||rcon
> EPL_RETRANSMISSION
|| scon
> EPL_RETRANSMISSION
)
3742 if(seq_recv
>= EPL_MAX_SEQUENCE
)
3744 expert_add_info(pinfo
, epl_tree
, &ei_recvseq_value
);
3746 if(seq_send
>= EPL_MAX_SEQUENCE
)
3748 expert_add_info(pinfo
, epl_tree
, &ei_sendseq_value
);
3751 epl_set_sequence_nr(pinfo
, 0x00);
3755 /* if retransmission request or connection valid with acknowledge request */
3756 if((rcon
== EPL_VALID
&& scon
== EPL_RETRANSMISSION
) || (rcon
== EPL_RETRANSMISSION
&& scon
== EPL_VALID
))
3758 /* replace the saved frame with the new frame */
3759 epl_duplication_insert(epl_duplication_table
, key
, frame
);
3761 /* if connection valid */
3764 /* store the new frame in the hash table */
3765 if(saved_frame
== 0x00)
3767 /* store the new frame in the hash table */
3768 epl_duplication_insert(epl_duplication_table
,key
,frame
);
3770 /* if the frame is bigger than the stored frame + the max frame offset
3771 or the saved frame is bigger that the current frame then store the current
3773 else if(((frame
> (saved_frame
+ EPL_MAX_FRAME_OFFSET
))
3774 ||(saved_frame
> frame
)))
3776 /* store the new frame in the hash table */
3777 epl_duplication_insert(epl_duplication_table
,key
,frame
);
3779 else if((frame
< (saved_frame
+ EPL_MAX_FRAME_OFFSET
))
3780 &&(frame
> saved_frame
))
3786 /* if the frame is a duplicated frame */
3787 seqnum
= epl_get_sequence_nr(pinfo
);
3788 if((duplication
== 0x01 && seqnum
== 0x00)||(seqnum
== 0x01))
3791 epl_set_sequence_nr(pinfo
, seqnum
);
3792 expert_add_info_format(pinfo
, epl_tree
, &ei_duplicated_frame
,
3793 "Duplication of Frame: %d ReceiveSequenceNumber: %d and SendSequenceNumber: %d ",
3794 saved_frame
,seq_recv
,seq_send
);
3796 /* if the last frame in the ReceiveSequence is sent get new memory */
3797 if(seq_recv
== 0x3f && seq_send
<= 0x3f)
3799 /* reset all entries of the transfer */
3800 epl_duplication_remove(epl_duplication_table
,epl_segmentation
.src
,epl_segmentation
.dest
);
3803 item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_seq
, tvb
, offset
, 5, ENC_NA
);
3804 sod_seq_tree
= proto_item_add_subtree(item
, ett_epl_sdo_sequence_layer
);
3805 /* Asynchronous SDO Sequence Layer */
3806 seq_recv
= tvb_get_uint8(tvb
, offset
);
3808 proto_tree_add_uint(sod_seq_tree
, hf_epl_asnd_sdo_seq_receive_sequence_number
, tvb
, offset
, 1, seq_recv
);
3809 proto_tree_add_uint(sod_seq_tree
, hf_epl_asnd_sdo_seq_receive_con
, tvb
, offset
, 1, seq_recv
);
3812 *seq
= seq_send
= tvb_get_uint8(tvb
, offset
);
3814 proto_tree_add_uint(sod_seq_tree
, hf_epl_asnd_sdo_seq_send_sequence_number
, tvb
, offset
, 1, seq_send
);
3815 proto_tree_add_uint(sod_seq_tree
, hf_epl_asnd_sdo_seq_send_con
, tvb
, offset
, 1, seq_send
);
3818 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Seq:%02d%s,%02d%s",
3819 seq_recv
>> EPL_ASND_SDO_SEQ_MASK
, val_to_str_const(seq_recv
& EPL_ASND_SDO_SEQ_CON_MASK
, epl_sdo_init_abbr_vals
, "x"),
3820 seq_send
>> EPL_ASND_SDO_SEQ_MASK
, val_to_str_const(seq_send
& EPL_ASND_SDO_SEQ_CON_MASK
, epl_sdo_init_abbr_vals
, "x"));
3822 seq_recv
&= EPL_ASND_SDO_SEQ_CON_MASK
;
3823 seq_send
&= EPL_ASND_SDO_SEQ_CON_MASK
;
3825 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%s) ", val_to_str_const((seq_recv
<< 8) | seq_send
, epl_sdo_init_con_vals
, "Invalid"));
3831 dissect_epl_sdo_command(proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t seq
)
3834 uint8_t segmented
, command_id
, transaction_id
;
3835 bool response
, abort_flag
;
3836 uint32_t abort_code
= 0;
3837 uint32_t fragmentId
= 0, remlength
= 0;
3838 uint16_t segment_size
= 0;
3839 proto_tree
*sdo_cmd_tree
= NULL
;
3841 uint8_t sendCon
= 0;
3842 unsigned is_response
= 0;
3846 sendCon
= tvb_get_uint8(tvb
, 5) & EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ
;
3848 command_id
= tvb_get_uint8(tvb
, offset
+ 2);
3849 abort_flag
= tvb_get_uint8(tvb
, offset
+ 1) & EPL_ASND_SDO_CMD_ABORT_FILTER
;
3851 /* test if CommandField == empty */
3852 if (command_id
!= 0 || abort_flag
)
3854 item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd
, tvb
, offset
, 0, ENC_NA
);
3855 sdo_cmd_tree
= proto_item_add_subtree(item
, ett_epl_sdo_command_layer
);
3857 transaction_id
= tvb_get_uint8(tvb
, offset
);
3858 response
= tvb_get_uint8(tvb
, offset
+ 1) & EPL_ASND_SDO_CMD_RESPONSE_FILTER
;
3859 segmented
= (tvb_get_uint8(tvb
, offset
+ 1) & EPL_ASND_SDO_CMD_SEGMENTATION_FILTER
) >> 4;
3861 segment_size
= tvb_get_letohs(tvb
, offset
+ 3);
3863 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cmd:%s,TID=%02d ",
3864 val_to_str(segmented
, epl_sdo_asnd_cmd_segmentation_abbr
, " Inv(%d)"), transaction_id
);
3866 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_transaction_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3869 proto_tree_add_item_ret_uint(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_response
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &is_response
);
3870 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_abort
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3872 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_segmentation
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3875 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_command_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3878 item
= proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_segment_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3880 if ( tvb_reported_length_remaining(tvb
, offset
) < segment_size
)
3881 expert_add_info_format(pinfo
, item
, &ei_real_length_differs
,
3882 "Captured length differs, only %d octets will be displayed", tvb_reported_length_remaining(tvb
, offset
) - 4 );
3884 if (segmented
== EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
3886 if((command_id
== EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
) || (command_id
== EPL_ASND_SDO_COMMAND_READ_BY_INDEX
))
3888 if (sendCon
!= EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ
)
3890 /* if download => reset counter */
3891 if(command_id
== EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
)
3893 /* if upload => reset counter */
3894 else if(command_id
== EPL_ASND_SDO_COMMAND_READ_BY_INDEX
)
3897 /* payload length */
3898 payload_length
= tvb_reported_length_remaining(tvb
, offset
);
3899 /* create a key for reassembly => first 16 bit are src-address and
3900 last 16 bit are the dest-address */
3901 fragmentId
= (uint32_t)((((uint32_t)epl_segmentation
.src
)<<16)+epl_segmentation
.dest
);
3902 /* set fragmented flag */
3903 pinfo
->fragmented
= true;
3904 fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
3905 fragmentId
, NULL
, 0, payload_length
, true );
3906 fragment_add_seq_offset ( &epl_reassembly_table
, pinfo
, fragmentId
, NULL
, 0 );
3907 if (command_id
== EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
)
3909 first_write
= false;
3915 /* if Segmentation = Initiate then print DataSize */
3916 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3923 /* if Segmentation = Initiate then print DataSize */
3924 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3931 remlength
= tvb_captured_length_remaining(tvb
, offset
);
3932 if (command_id
== EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
&& response
)
3934 /* the SDO response can contain several abort codes for multiple transfers */
3935 while (remlength
> 0)
3937 /* TODO enhance Index and SubIndex with string representation */
3938 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
3941 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3944 proto_tree_add_item(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_sub_abort
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
3947 abort_code
= tvb_get_letohl(tvb
, offset
);
3948 /* if AbortBit is set then print AbortMessage */
3949 proto_tree_add_uint(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_abort_code
, tvb
, offset
, 4, abort_code
);
3950 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Abort:0x%08X (%s)", abort_code
, val_to_str_ext_const(abort_code
, &sdo_cmd_abort_code_ext
, "Unknown"));
3953 remlength
= tvb_captured_length_remaining(tvb
, offset
);
3958 abort_code
= tvb_get_letohl(tvb
, offset
);
3959 /* if AbortBit is set then print AbortMessage */
3960 proto_tree_add_uint(sdo_cmd_tree
, hf_epl_asnd_sdo_cmd_abort_code
, tvb
, offset
, 4, abort_code
);
3961 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Abort:0x%08X (%s)", abort_code
, val_to_str_ext_const(abort_code
, &sdo_cmd_abort_code_ext
, "Unknown"));
3966 int opts
= is_response
? CONVO_FOR_RESPONSE
: CONVO_FOR_REQUEST
;
3967 struct epl_convo
*convo
= epl_get_convo(pinfo
, opts
);
3968 convo
->seq_send
= seq
;
3972 case EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
:
3973 offset
= dissect_epl_sdo_command_write_by_index(convo
, sdo_cmd_tree
, tvb
, pinfo
, offset
, segmented
, response
, segment_size
);
3976 case EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
:
3977 offset
= dissect_epl_sdo_command_write_multiple_by_index(convo
, sdo_cmd_tree
, tvb
, pinfo
, offset
, segmented
, response
, segment_size
);
3980 case EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX
:
3981 offset
= dissect_epl_sdo_command_read_multiple_by_index(convo
, sdo_cmd_tree
, tvb
, pinfo
, offset
, segmented
, response
, segment_size
);
3984 case EPL_ASND_SDO_COMMAND_READ_BY_INDEX
:
3985 offset
= dissect_epl_sdo_command_read_by_index(convo
, sdo_cmd_tree
, tvb
, pinfo
, offset
, segmented
, response
, segment_size
);
3997 dissect_epl_sdo_command_write_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
)
3999 int size
, payload_length
, rem_size
= 0;
4000 uint16_t idx
= 0x00, sod_index
= 0xFF, error
= 0xFF, sub_val
= 0x00;
4002 uint8_t subindex
= 0x00;
4003 uint32_t fragmentId
= 0;
4005 bool end_segment
= false;
4006 proto_item
*psf_item
, *cmd_payload
;
4007 proto_tree
*payload_tree
;
4008 const char *index_str
, *sub_str
, *sub_index_str
;
4009 fragment_head
*frag_msg
= NULL
;
4010 struct object
*obj
= NULL
;
4011 const struct subobject
*subobj
= NULL
;
4013 /* get the current frame number */
4019 if (segmented
<= EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
4021 /* get index offset */
4022 idx
= tvb_get_letohs(tvb
, offset
);
4023 /* add index item */
4024 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
4025 /* look up index in registered profile */
4026 obj
= object_lookup(convo
->profile
, idx
);
4029 /* value to string */
4030 index_str
= rval_to_str_const(idx
, sod_cmd_str
, "unknown");
4031 /* get index string value */
4032 sod_index
= str_to_val(index_str
, sod_cmd_str_val
, error
);
4034 /* get subindex string */
4035 sub_index_str
= val_to_str_ext_const(idx
, &sod_cmd_no_sub
, "unknown");
4036 /* get subindex string value */
4037 nosub
= str_to_val(sub_index_str
, sod_cmd_str_no_sub
, 0xFF) != 0xFF;
4041 /* get subindex offset */
4042 subindex
= tvb_get_uint8(tvb
, offset
);
4043 subobj
= subobject_lookup(obj
, subindex
);
4046 /* get subindex string */
4047 sub_str
= val_to_str_ext_const(subindex
, &sod_cmd_sub_str
, "unknown");
4048 /* get string value */
4049 sub_val
= str_to_val(sub_str
, sod_cmd_sub_str_val
, error
);
4051 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s[%d]: (0x%04X/%d)",
4052 val_to_str_ext(EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX
, &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
4053 segment_size
, idx
, subindex
);
4055 if (obj
|| sod_index
== error
)
4057 const char *name
= obj
? obj
->info
.name
: val_to_str_ext_const(((uint32_t)(idx
<<16)), &sod_index_names
, "User Defined");
4058 proto_item_append_text(psf_item
, " (%s)", name
);
4059 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s", name
);
4060 if (obj
) nosub
= obj
->info
.type_class
== OD_ENTRY_SCALAR
;
4062 else /* string is in list */
4064 /* add index string to index item */
4065 proto_item_append_text(psf_item
," (%s", val_to_str_ext_const(((uint32_t)(sod_index
<<16)), &sod_index_names
, "User Defined"));
4066 proto_item_append_text(psf_item
,"_%02Xh", (idx
-sod_index
));
4067 if(sod_index
== EPL_SOD_PDO_RX_MAPP
|| sod_index
== EPL_SOD_PDO_TX_MAPP
)
4069 proto_item_append_text(psf_item
,"_AU64)");
4073 proto_item_append_text(psf_item
,"_REC)");
4076 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s", val_to_str_ext_const(((uint32_t)(sod_index
<< 16)), &sod_index_names
, "User Defined"));
4077 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "_%02Xh", (idx
-sod_index
));
4078 if(sod_index
== EPL_SOD_PDO_RX_MAPP
|| sod_index
== EPL_SOD_PDO_TX_MAPP
)
4080 col_append_str(pinfo
->cinfo
, COL_INFO
, "_AU64");
4084 col_append_str(pinfo
->cinfo
, COL_INFO
, "_REC");
4089 if(sub_val
!= error
)
4094 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
4095 proto_item_append_text(psf_item
, " (%s)", subobj
->info
.name
);
4096 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%s)", subobj
->info
.name
);
4098 /* if the subindex is a EPL_SOD_STORE_PARAM */
4099 /* if the subindex is a EPL_SOD_RESTORE_PARAM */
4100 else if((idx
== EPL_SOD_STORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04) ||
4101 (idx
== EPL_SOD_RESTORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04))
4103 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
4104 proto_item_append_text(psf_item
, " (ManufacturerParam_%02Xh_U32)", subindex
);
4105 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/ManufacturerParam_%02Xh_U32)", subindex
);
4107 /* if the subindex is a EPL_SOD_PDO_RX_MAPP */
4108 /* if the subindex is a EPL_SOD_PDO_TX_MAPP */
4109 else if((idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe) ||
4110 (idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe))
4112 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
4113 proto_item_append_text(psf_item
, " (ObjectMapping)");
4114 col_append_str(pinfo
->cinfo
, COL_INFO
, "/ObjectMapping)");
4119 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
4121 else if(subindex
== 0x00)
4123 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
4124 proto_item_append_text(psf_item
, " (NumberOfEntries)");
4125 col_append_str(pinfo
->cinfo
, COL_INFO
, "/NumberOfEntries)");
4129 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
4130 proto_item_append_text(psf_item
, " (%s)", val_to_str_ext_const((subindex
| (idx
<< 16)), &sod_index_names
, "User Defined"));
4131 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%s)",val_to_str_ext_const((subindex
| (idx
<< 16)), &sod_index_names
, "User Defined"));
4136 else if((segmented
== EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE
) ||
4137 (segmented
== EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT
))
4139 /* get the fragmentId */
4140 fragmentId
= (uint32_t)((((uint32_t)epl_segmentation
.src
)<<16)+epl_segmentation
.dest
);
4141 /* set the fragmented flag */
4142 pinfo
->fragmented
= true;
4144 /* get payload size */
4145 payload_length
= tvb_reported_length_remaining(tvb
, offset
);
4146 /* if the frame is the last frame */
4147 if(segmented
== EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE
)
4150 /* if the send-sequence-number is at the end or the beginning of a sequence */
4151 if(epl_segmentation
.send
== 0x3f || epl_segmentation
.send
<= 0x01 )
4154 memset(&epl_asnd_sdo_reassembly_write
,0,sizeof(epl_sdo_reassembly
));
4155 /* save the current frame and increase the counter */
4156 epl_asnd_sdo_reassembly_write
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] = frame
;
4158 /* add the frame to reassembly_table */
4159 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
4160 fragmentId
, NULL
, ct
, payload_length
, end_segment
? false : true );
4164 if(epl_asnd_sdo_reassembly_write
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == 0x00)
4166 /* save the current frame and increase counter */
4167 epl_asnd_sdo_reassembly_write
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] = frame
;
4169 /* add the frame to reassembly_table */
4172 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
4173 fragmentId
, NULL
, 0, payload_length
, end_segment
? false : true );
4174 fragment_add_seq_offset(&epl_reassembly_table
, pinfo
, fragmentId
, NULL
, ct
);
4176 first_write
= false;
4180 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
4181 fragmentId
, NULL
, ct
, payload_length
, end_segment
? false : true );
4186 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
4187 fragmentId
, NULL
, 0, payload_length
, end_segment
? false : true);
4188 epl_asnd_sdo_reassembly_write
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] = frame
;
4192 /* if the reassembly_table is not Null and the frame stored is the same as the current frame */
4193 if(frag_msg
!= NULL
&& (epl_asnd_sdo_reassembly_write
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == frame
))
4195 /* if the frame is the last frame */
4198 cmd_payload
= proto_tree_add_uint_format(epl_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, offset
, payload_length
,0,
4199 "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg
->len
,payload_length
);
4200 payload_tree
= proto_item_add_subtree(cmd_payload
, ett_epl_asnd_sdo_data_reassembled
);
4201 /* add the reassembly fields */
4202 process_reassembled_data(tvb
, 0, pinfo
, "Reassembled Message", frag_msg
, &epl_frag_items
, NULL
, payload_tree
);
4203 proto_tree_add_uint_format_value(payload_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, 0, 0,
4204 payload_length
, "%d bytes (over all fragments)", frag_msg
->len
);
4205 col_append_str(pinfo
->cinfo
, COL_INFO
, " (Message Reassembled)" );
4209 cmd_payload
= proto_tree_add_uint_format(epl_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, offset
, payload_length
,0,
4210 "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg
->len
,payload_length
);
4211 payload_tree
= proto_item_add_subtree(cmd_payload
, ett_epl_asnd_sdo_data_reassembled
);
4212 /* add reassemble field => Reassembled in: */
4213 process_reassembled_data(tvb
, 0, pinfo
, "Reassembled Message", frag_msg
, &epl_frag_items
, NULL
, payload_tree
);
4219 /* determine remaining SDO payload size (depends on segment size of current command) */
4220 size
= tvb_reported_length_remaining(tvb
, offset
);
4221 if(size
> (segment_size
- 4))
4223 rem_size
= (segment_size
- 4);
4230 /* if the frame is a PDO Mapping and the subindex is bigger than 0x00 */
4231 if((idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
> 0x00) || (idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
> 0x00))
4233 wmem_array_t
*mappings
= NULL
;
4234 if (use_sdo_mappings
)
4235 mappings
= idx
== EPL_SOD_PDO_TX_MAPP
? convo
->TPDO
: convo
->RPDO
;
4237 offset
= dissect_object_mapping(convo
->profile
, mappings
, epl_tree
, tvb
, pinfo
->num
, offset
, idx
, subindex
);
4241 /* dissect the payload */
4242 const struct epl_datatype
*type
= NULL
;
4244 type
= subobj
->info
.type
;
4246 type
= obj
->info
.type
;
4248 offset
= dissect_epl_payload(epl_tree
, tvb
, pinfo
, offset
, rem_size
, type
, EPL_ASND
);
4253 /* response, no payload */
4254 col_append_str(pinfo
->cinfo
, COL_INFO
, "Response");
4259 /* epl_tree may be null here, when this function is called from the profile parser */
4261 dissect_object_mapping(struct profile
*profile
, wmem_array_t
*mappings
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, uint32_t framenum
, int offset
, uint16_t idx
, uint8_t subindex
)
4263 proto_item
*ti_obj
, *ti_subobj
, *psf_item
;
4264 proto_tree
*psf_tree
;
4265 struct object_mapping map
= OBJECT_MAPPING_INITIALIZER
;
4266 struct object
*mapping_obj
;
4268 const struct subobject
*mapping_subobj
;
4271 /* If we don't populate the tree or record mappings, skip over it */
4272 if (!epl_tree
&& !mappings
)
4273 return offset
+ EPL_OBJECT_MAPPING_SIZE
;
4275 map
.param
.idx
= idx
;
4276 map
.param
.subindex
= subindex
;
4277 map
.frame
.first
= framenum
;
4278 map
.frame
.last
= UINT32_MAX
;
4280 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_mapping
, tvb
, offset
, 1, ENC_NA
);
4281 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sdo_cmd_data_mapping
);
4283 map
.pdo
.idx
= tvb_get_letohs(tvb
, offset
);
4284 ti_obj
= proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_index
, tvb
, offset
, 2, map
.pdo
.idx
,"Index: 0x%04X", map
.pdo
.idx
);
4287 map
.pdo
.subindex
= tvb_get_uint8(tvb
, offset
);
4288 ti_subobj
= proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_subindex
, tvb
, offset
, 1, map
.pdo
.subindex
, "SubIndex: 0x%02X", map
.pdo
.subindex
);
4291 /* look up index in registered profiles */
4292 if ((mapping_obj
= object_lookup(profile
, map
.pdo
.idx
)))
4294 if (!map
.pdo
.subindex
&& mapping_obj
->info
.type_class
== OD_ENTRY_SCALAR
)
4297 map
.info
= &mapping_obj
->info
;
4298 map
.index_name
= map
.info
->name
;
4299 proto_item_append_text (ti_obj
, " (%s)", map
.info
->name
);
4301 mapping_subobj
= subobject_lookup(mapping_obj
, map
.pdo
.subindex
);
4304 map
.info
= &mapping_subobj
->info
;
4305 proto_item_append_text (ti_subobj
, " (%s)", map
.info
->name
);
4309 proto_item_set_hidden(ti_subobj
);
4313 map
.bit_offset
= tvb_get_letohs(tvb
, offset
);
4314 proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_offset
, tvb
, offset
, 2, map
.bit_offset
,"Offset: 0x%04X", map
.bit_offset
);
4317 map
.no_of_bits
= tvb_get_uint8(tvb
, offset
);
4318 psf_item
= proto_tree_add_item(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
4319 proto_item_append_text(psf_item
, " bits");
4324 /* We leak an ett entry every time we destruct a mapping
4325 * Not sure what to do about that
4327 proto_register_subtree_array(&ett
, 1);
4331 /* TODO One could think of a better string here? */
4333 snprintf(map
.title
, sizeof(map
.title
), "PDO - %04X", map
.pdo
.idx
);
4335 snprintf(map
.title
, sizeof(map
.title
), "PDO - %04X:%02X", map
.pdo
.idx
, map
.pdo
.subindex
);
4337 add_object_mapping(mappings
, &map
);
4344 dissect_epl_sdo_command_write_multiple_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
)
4347 uint8_t subindex
= 0x00, padding
= 0x00;
4348 uint16_t idx
= 0x00, error
= 0xFF, sub_val
= 0x00;
4350 uint32_t size
, offsetincrement
, datalength
, remlength
, objectcnt
, abort_code
= 0;
4351 bool lastentry
= false, is_abort
= false;
4352 const char *index_str
, *sub_str
, *sub_index_str
;
4353 proto_item
*psf_item
;
4354 proto_tree
*psf_od_tree
;
4355 struct object
*obj
= NULL
;
4356 const struct subobject
*subobj
= NULL
;
4357 uint16_t segment_restsize
= segment_size
;
4360 /* Offset is calculated simply by only applying EPL payload offset, not packet offset.
4361 * The packet offset is 16, as this is the number of bytes trailing the SDO payload.
4362 * EPL_SOA_EPLV_OFFSET has to be recognized, because the increment of PLK SDO payloads
4363 * is calculated, starting with the byte position AFTER the Sequence Layer.
4368 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s[%d]:",
4369 val_to_str_ext(EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
,
4370 &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
4373 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4376 /* As long as no lastentry has been detected, and we have still bytes left,
4377 * we start the loop. lastentry is probably not necessary anymore, since
4378 * we now use length_remaining, but it is kept to be on the safe side. */
4379 while ( !lastentry
&& remlength
> 0 )
4381 uint16_t sod_index
= error
;
4383 offsetincrement
= tvb_get_letohl(tvb
, offset
);
4385 /* the data is aligned in 4-byte increments, therefore maximum padding is 3 */
4386 padding
= tvb_get_uint8 ( tvb
, offset
+ 7 ) & 0x03;
4388 /* An offset increment of zero usually indicates, that we are at the end
4389 * of the payload. But we cannot ignore the end, because packages are
4390 * stacked up until the last byte */
4391 if (offsetincrement
== 0)
4393 datalength
= segment_restsize
;
4398 datalength
= offsetincrement
- (offset
- EPL_SOA_EPLV_OFFSET
);
4400 /* decrease restsize */
4401 segment_restsize
-= datalength
;
4403 /* Possible unsigned overflow */
4404 if ( datalength
> remlength
)
4407 /* Each entry has a header size of 8, based on the following calculation:
4408 * - 4 byte for byte position of next data set
4409 * - 2 byte for index
4410 * - 1 byte for subindex
4411 * - 1 byte for reserved and padding */
4413 /* Guarding against readout of padding. Probability is nearly zero, as
4414 * padding was checked above, but to be sure, this remains here */
4415 if ((uint32_t)(padding
+ 8) >= datalength
)
4418 /* size of data is datalength - ( entry header size and padding ) */
4419 size
= datalength
- 8 - padding
;
4421 dataoffset
= offset
+ 4;
4423 /* add object subtree */
4424 psf_od_tree
= proto_tree_add_subtree(epl_tree
, tvb
, offset
+4, 4+size
, 0, NULL
, "OD");
4426 if (segmented
<= EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
4428 /* get SDO index value */
4429 idx
= tvb_get_letohs(tvb
, dataoffset
);
4430 /* add index item */
4431 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, offset
+4, 2, ENC_LITTLE_ENDIAN
);
4432 /* Check profile for name */
4433 obj
= object_lookup(convo
->profile
, idx
);
4436 /* value to string */
4437 index_str
= rval_to_str_const(idx
, sod_cmd_str
, "unknown");
4438 /* get index string value */
4439 sod_index
= str_to_val(index_str
, sod_cmd_str_val
, error
);
4441 /* get subindex string */
4442 sub_index_str
= val_to_str_ext_const(idx
, &sod_cmd_no_sub
, "unknown");
4443 /* get subindex string value*/
4444 nosub
= str_to_val(sub_index_str
, sod_cmd_str_no_sub
, 0xFF) != 0xFF;
4447 if(sod_index
== error
)
4449 const char *name
= obj
? obj
->info
.name
:val_to_str_ext_const(((uint32_t)(idx
<<16)), &sod_index_names
, "User Defined");
4450 proto_item_append_text(psf_item
," (%s)", name
);
4454 /* add index string */
4455 proto_item_append_text(psf_item
," (%s", val_to_str_ext_const(((uint32_t)(sod_index
<<16)), &sod_index_names
, "User Defined"));
4456 proto_item_append_text(psf_item
,"_%02Xh", (idx
-sod_index
));
4457 if(sod_index
== EPL_SOD_PDO_RX_MAPP
|| sod_index
== EPL_SOD_PDO_TX_MAPP
)
4459 proto_item_append_text(psf_item
,"_AU64)");
4463 proto_item_append_text(psf_item
,"_REC)");
4468 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (0x%04X", idx
);
4470 col_append_str(pinfo
->cinfo
, COL_INFO
, ".");
4474 proto_item_append_text(psf_od_tree
, " Idx: 0x%04X", idx
);
4476 if (sod_index
!= error
)
4479 /* get subindex offset */
4480 subindex
= tvb_get_uint8(tvb
, dataoffset
);
4481 subobj
= subobject_lookup(obj
, subindex
);
4482 proto_item_append_text(psf_od_tree
, " SubIdx: 0x%02X", subindex
);
4483 /* get subindex string */
4484 sub_str
= val_to_str_ext_const(idx
, &sod_cmd_sub_str
, "unknown");
4485 /* get string value */
4486 sub_val
= str_to_val(sub_str
, sod_cmd_sub_str_val
,error
);
4488 if(sub_val
!= error
)
4493 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4494 proto_item_append_text(psf_item
, " (%s)", subobj
->info
.name
);
4496 /* if the subindex is a EPL_SOD_STORE_PARAM */
4497 else if(idx
== EPL_SOD_STORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04)
4499 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4500 proto_item_append_text(psf_item
, " (ManufacturerParam_%02Xh_U32)", subindex
);
4502 /* if the subindex is a EPL_SOD_RESTORE_PARAM */
4503 else if(idx
== EPL_SOD_RESTORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04)
4505 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4506 proto_item_append_text(psf_item
, " (ManufacturerParam_%02Xh_U32)", subindex
);
4508 /* if the subindex is a EPL_SOD_PDO_RX_MAPP */
4509 else if(idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
4511 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4512 proto_item_append_text(psf_item
, " (ObjectMapping)");
4514 /* if the subindex is a EPL_SOD_PDO_TX_MAPP */
4515 else if(idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
4517 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4518 proto_item_append_text(psf_item
, " (ObjectMapping)");
4520 /* if the subindex has the value 0x00 */
4521 else if(subindex
== 0x00)
4523 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4524 proto_item_append_text(psf_item
, " (NumberOfEntries)");
4529 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4530 proto_item_append_text(psf_item
, " (%s)", val_to_str_ext_const((subindex
| (idx
<< 16)), &sod_index_names
, "User Defined"));
4538 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
4540 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%d)", subindex
);
4545 proto_tree_add_uint(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_padding
, tvb
, dataoffset
, 1, padding
);
4550 /* size of embedded data */
4551 psf_item
= proto_tree_add_uint_format(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_size
, tvb
, dataoffset
, size
, size
, "Data size: %d byte", size
);
4552 proto_item_set_generated(psf_item
);
4554 /* if the frame is a PDO Mapping and the subindex is bigger than 0x00 */
4555 if((idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
> 0x00) ||(idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
> 0x00))
4557 wmem_array_t
*mappings
= NULL
;
4558 if (use_sdo_mappings
)
4559 mappings
= idx
== EPL_SOD_PDO_TX_MAPP
? convo
->TPDO
: convo
->RPDO
;
4560 dissect_object_mapping(convo
->profile
, mappings
, psf_od_tree
, tvb
, pinfo
->num
, dataoffset
, idx
, subindex
);
4562 else /* dissect the payload */
4564 const struct epl_datatype
*type
= NULL
;
4566 type
= subobj
->info
.type
;
4568 type
= obj
->info
.type
;
4570 dissect_epl_payload(psf_od_tree
, tvb
, pinfo
, dataoffset
, size
, type
, EPL_ASND
);
4573 offset
+= datalength
;
4575 /* calculating the remaining length, based on the current offset */
4576 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4579 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d)", objectcnt
);
4583 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Response %s[%d]:",
4584 val_to_str_ext(EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX
,
4585 &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
4588 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4591 dataoffset
= offset
;
4593 /* As long as no lastentry has been detected, and we have still bytes left,
4594 * we start the loop. */
4595 while ( remlength
> 0 )
4598 if ((tvb_get_uint8 ( tvb
, offset
+ 3 ) & 0x80) == 0x80)
4601 /* add object subtree */
4602 psf_od_tree
= proto_tree_add_subtree(epl_tree
, tvb
, offset
, 8, 0, NULL
, "OD");
4604 if (segmented
<= EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
4606 /* get SDO index value */
4607 idx
= tvb_get_letohs(tvb
, dataoffset
);
4608 /* value to string */
4609 index_str
= rval_to_str_const(idx
, sod_cmd_str
, "unknown");
4610 /* get index string value */
4611 sod_index
= str_to_val(index_str
, sod_cmd_str_val
, error
);
4612 /* get subindex string */
4613 sub_index_str
= val_to_str_ext_const(idx
, &sod_cmd_no_sub
, "unknown");
4614 /* get subindex string value*/
4615 nosub
= str_to_val(sub_index_str
, sod_cmd_str_no_sub
,error
);
4618 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (0x%04X", idx
);
4620 col_append_str(pinfo
->cinfo
, COL_INFO
, ".");
4622 proto_tree_add_uint_format(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_mapping_index
, tvb
, dataoffset
, 2, idx
,"Index: 0x%04X", idx
);
4623 proto_item_append_text(psf_od_tree
, " Idx: 0x%04X", idx
);
4625 if (sod_index
!= error
)
4630 /* get subindex offset */
4631 subindex
= tvb_get_uint8(tvb
, dataoffset
);
4632 proto_item_append_text(psf_od_tree
, " SubIdx: 0x%02X", subindex
);
4633 proto_tree_add_uint_format(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_mapping_subindex
, tvb
, dataoffset
, 1, idx
,"SubIndex: 0x%02X", subindex
);
4640 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
4642 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%d)", subindex
);
4647 proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_sub_abort
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4653 abort_code
= tvb_get_letohl(tvb
, dataoffset
);
4655 proto_item_append_text(psf_od_tree
, " - %s", "Aborted");
4657 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_sdo_multi_param_sub_abort
, tvb
, dataoffset
, 4, ENC_LITTLE_ENDIAN
);
4658 proto_item_append_text(psf_item
," (%s)", val_to_str_ext_const(abort_code
, &sdo_cmd_abort_code_ext
, "Unknown"));
4666 /* each sub response is 8 bytes */
4669 /* calculating the remaining length, based on the current offset */
4670 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4673 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d)", objectcnt
);
4678 dissect_epl_sdo_command_read_multiple_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
)
4681 uint8_t subindex
= 0x00, padding
= 0x00;
4682 uint16_t idx
= 0x00, error
= 0xFF, sub_val
= 0x00;
4684 uint32_t size
, offsetincrement
, datalength
, remlength
, objectcnt
, abort_code
;
4685 bool lastentry
= false, is_abort
= false;
4686 const char *index_str
, *sub_str
, *sub_index_str
;
4687 proto_item
*psf_item
, *psf_od_item
;
4688 proto_tree
*psf_tree
, *psf_od_tree
;
4689 struct object
*obj
= NULL
;
4690 const struct subobject
*subobj
= NULL
;
4692 uint16_t segment_restsize
= segment_size
;
4694 /* Offset is calculated simply by only applying EPL payload offset, not packet offset.
4695 * The packet offset is 16, as this is the number of bytes trailing the SDO payload.
4696 * EPL_SOA_EPLV_OFFSET has to be recognized, because the increment of PLK SDO payloads
4697 * is calculated, starting with the byte position AFTER the Sequence Layer.
4701 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s[%d]:",
4702 val_to_str_ext(EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX
,
4703 &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
4706 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4709 /* As long as no lastentry has been detected, and we have still bytes left,
4710 * we start the loop. lastentry is probably not necessary anymore, since
4711 * we now use length_remaining, but it is kept to be on the safe side. */
4712 while ( !lastentry
&& remlength
> 0 )
4714 uint16_t sod_index
= error
;
4716 offsetincrement
= tvb_get_letohl(tvb
, offset
);
4718 /* the data is aligned in 4-byte increments, therefor maximum padding is 3 */
4719 padding
= tvb_get_uint8 ( tvb
, offset
+ 7 ) & 0x03;
4721 if ((tvb_get_uint8 ( tvb
, offset
+ 7 ) & 0x80) == 0x80)
4724 /* An offset increment of zero usually indicates, that we are at the end
4725 * of the payload. But we cannot ignore the end, because packages are
4726 * stacked up until the last byte */
4727 if (offsetincrement
== 0)
4729 datalength
= segment_restsize
;
4734 datalength
= offsetincrement
- (offset
- EPL_SOA_EPLV_OFFSET
);
4736 /* decrease restsize */
4737 segment_restsize
-= datalength
;
4739 /* Possible unsigned overflow */
4740 if (datalength
> remlength
)
4743 /* Each entry has a header size of 8, based on the following calculation:
4744 * - 4 byte for byte position of next data set
4745 * - 2 byte for index
4746 * - 1 byte for subindex
4747 * - 1 byte for reserved and padding */
4749 /* Guarding against readout of padding. Probability is nearly zero, as
4750 * padding was checked above, but to be sure, this remains here */
4751 if ((uint32_t)(padding
+ 8) >= datalength
)
4754 /* size of data is datalength - ( entry header size and padding ) */
4755 size
= datalength
- 8 - padding
;
4757 dataoffset
= offset
+ 4;
4759 /* add object subtree */
4760 psf_od_tree
= proto_tree_add_subtree(epl_tree
, tvb
, offset
+4, 4+size
, 0, NULL
, "OD");
4762 if (segmented
<= EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
4764 /* get SDO index value */
4765 idx
= tvb_get_letohs(tvb
, dataoffset
);
4766 obj
= object_lookup(convo
->profile
, idx
);
4769 /* value to string */
4770 index_str
= rval_to_str_const(idx
, sod_cmd_str
, "unknown");
4771 /* get index string value */
4772 sod_index
= str_to_val(index_str
, sod_cmd_str_val
, error
);
4773 /* get subindex string */
4774 sub_index_str
= val_to_str_ext_const(idx
, &sod_cmd_no_sub
, "unknown");
4775 /* get subindex string value*/
4776 nosub
= str_to_val(sub_index_str
, sod_cmd_str_no_sub
, 0xFF) != 0xFF;
4778 /* add index item */
4779 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, offset
+4, 2, ENC_LITTLE_ENDIAN
);
4783 proto_item_append_text(psf_item
, " (%s)", obj
->info
.name
);
4784 nosub
= obj
->info
.type_class
== OD_ENTRY_SCALAR
;
4786 else if(sod_index
== error
)
4788 proto_item_append_text(psf_item
," (%s)", val_to_str_ext_const(((uint32_t)(idx
<<16)), &sod_index_names
, "User Defined"));
4792 /* add index string */
4793 proto_item_append_text(psf_item
," (%s", val_to_str_ext_const(((uint32_t)(sod_index
<<16)), &sod_index_names
, "User Defined"));
4794 proto_item_append_text(psf_item
,"_%02Xh", (idx
-sod_index
));
4795 if(sod_index
== EPL_SOD_PDO_RX_MAPP
|| sod_index
== EPL_SOD_PDO_TX_MAPP
)
4797 proto_item_append_text(psf_item
,"_AU64)");
4801 proto_item_append_text(psf_item
,"_REC)");
4806 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (0x%04X", idx
);
4808 col_append_str(pinfo
->cinfo
, COL_INFO
, ".");
4810 if (sod_index
!= error
)
4813 proto_item_append_text(psf_od_tree
, " Idx: 0x%04X", idx
);
4817 /* get subindex offset */
4818 subindex
= tvb_get_uint8(tvb
, dataoffset
);
4819 subobj
= subobject_lookup(obj
, subindex
);
4820 proto_item_append_text(psf_od_tree
, " SubIdx: 0x%02X", subindex
);
4821 /* get subindex string */
4822 sub_str
= val_to_str_ext_const(idx
, &sod_cmd_sub_str
, "unknown");
4823 /* get string value */
4824 sub_val
= str_to_val(sub_str
, sod_cmd_sub_str_val
,error
);
4826 if(sub_val
!= error
)
4831 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4832 proto_item_append_text(psf_item
, " (%s)", subobj
->info
.name
);
4834 /* if the subindex is a EPL_SOD_STORE_PARAM */
4835 else if(idx
== EPL_SOD_STORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04)
4837 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4838 proto_item_append_text(psf_item
, " (ManufacturerParam_%02Xh_U32)", subindex
);
4840 /* if the subindex is a EPL_SOD_RESTORE_PARAM */
4841 else if(idx
== EPL_SOD_RESTORE_PARAM
&& subindex
<= 0x7F && subindex
>= 0x04)
4843 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4844 proto_item_append_text(psf_item
, " (ManufacturerParam_%02Xh_U32)", subindex
);
4846 /* if the subindex is a EPL_SOD_PDO_RX_MAPP */
4847 else if(idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
4849 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4850 proto_item_append_text(psf_item
, " (ObjectMapping)");
4852 /* if the subindex is a EPL_SOD_PDO_TX_MAPP */
4853 else if(idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
>= 0x01 && subindex
<= 0xfe)
4855 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4856 proto_item_append_text(psf_item
, " (ObjectMapping)");
4858 else if(subindex
== 0x00)
4860 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4861 proto_item_append_text(psf_item
, " (NumberOfEntries)");
4866 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, dataoffset
, 1, ENC_LITTLE_ENDIAN
);
4867 proto_item_append_text(psf_item
, " (%s)", val_to_str_ext_const((subindex
| (idx
<< 16)), &sod_index_names
, "User Defined"));
4875 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
4877 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%d)", subindex
);
4882 proto_tree_add_uint(psf_od_tree
, hf_epl_asnd_sdo_cmd_data_padding
, tvb
, dataoffset
, 1, padding
);
4890 proto_tree_add_item(psf_od_tree
, hf_epl_asnd_sdo_cmd_sub_abort
, tvb
, dataoffset
- 1, 1, ENC_LITTLE_ENDIAN
);
4892 abort_code
= tvb_get_letohl(tvb
, dataoffset
);
4894 proto_item_append_text(psf_od_tree
, " - %s", "Aborted");
4896 psf_item
= proto_tree_add_item(psf_od_tree
, hf_epl_sdo_multi_param_sub_abort
, tvb
, dataoffset
, 4, ENC_LITTLE_ENDIAN
);
4897 proto_item_append_text(psf_item
," (%s)", val_to_str_ext_const(abort_code
, &sdo_cmd_abort_code_ext
, "Unknown"));
4903 /* if the frame is a PDO Mapping and the subindex is bigger than 0x00 */
4904 if((idx
== EPL_SOD_PDO_TX_MAPP
&& subindex
> 0x00) ||(idx
== EPL_SOD_PDO_RX_MAPP
&& subindex
> 0x00))
4906 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_mapping
, tvb
, dataoffset
, 1, ENC_NA
);
4907 psf_tree
= proto_item_add_subtree(psf_item
, ett_epl_asnd_sdo_cmd_data_mapping
);
4908 idx
= tvb_get_letohs(tvb
, dataoffset
);
4909 proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_index
, tvb
, dataoffset
, 2, idx
,"Index: 0x%04X", idx
);
4911 idx
= tvb_get_letohs(tvb
, dataoffset
);
4912 proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_subindex
, tvb
, dataoffset
, 1, idx
,"SubIndex: 0x%02X", idx
);
4914 idx
= tvb_get_letohs(tvb
, dataoffset
);
4915 proto_tree_add_uint_format(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_offset
, tvb
, dataoffset
, 2, idx
,"Offset: 0x%04X", idx
);
4917 proto_tree_add_item(psf_tree
, hf_epl_asnd_sdo_cmd_data_mapping_length
, tvb
, dataoffset
, 2, ENC_LITTLE_ENDIAN
);
4921 /* dissect the payload */
4922 const struct epl_datatype
*type
= NULL
;
4924 type
= subobj
->info
.type
;
4926 type
= obj
->info
.type
;
4928 dissect_epl_payload ( psf_od_tree
, tvb
, pinfo
, dataoffset
, size
, type
, EPL_ASND
);
4932 offset
+= datalength
;
4934 /* calculating the remaining length, based on the current offset */
4935 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4938 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d)", objectcnt
);
4942 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Request %s[%d]:",
4943 val_to_str_ext(EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX
,
4944 &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
4947 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
4950 dataoffset
= offset
;
4952 /* As long as no lastentry has been detected, and we have still bytes left,
4953 * we start the loop. */
4954 while ( remlength
> 0 )
4956 uint16_t sod_index
= error
;
4957 proto_tree
*psf_entry
;
4958 /* add object subtree */
4959 psf_od_item
= proto_tree_add_subtree(epl_tree
, tvb
, offset
, 4, 0, NULL
, "OD");
4961 if (segmented
<= EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER
)
4963 /* get SDO index value */
4964 idx
= tvb_get_letohs(tvb
, dataoffset
);
4965 obj
= object_lookup(convo
->profile
, idx
);
4968 /* value to string */
4969 index_str
= rval_to_str_const(idx
, sod_cmd_str
, "unknown");
4970 /* get index string value */
4971 sod_index
= str_to_val(index_str
, sod_cmd_str_val
, error
);
4972 /* get subindex string */
4973 sub_index_str
= val_to_str_ext_const(idx
, &sod_cmd_no_sub
, "unknown");
4974 /* get subindex string value*/
4975 nosub
= str_to_val(sub_index_str
, sod_cmd_str_no_sub
,0xFF) != 0xFF;
4979 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (0x%04X", idx
);
4981 col_append_str(pinfo
->cinfo
, COL_INFO
, ".");
4983 if (sod_index
!= error
)
4986 proto_item_append_text(psf_od_item
, " Idx: 0x%04X", idx
);
4987 psf_entry
= proto_tree_add_uint_format(psf_od_item
, hf_epl_asnd_sdo_cmd_data_mapping_index
, tvb
, dataoffset
, 2, idx
,"Index: 0x%04X", idx
);
4991 proto_item_append_text(psf_entry
, " (%s)", obj
->info
.name
);
4992 nosub
= obj
->info
.type_class
== OD_ENTRY_SCALAR
;
4994 else if(sod_index
== error
)
4996 name
= val_to_str_ext_const(((uint32_t)(idx
<<16)), &sod_index_names
, "User Defined");
4997 proto_item_append_text(psf_entry
," (%s)", name
);
5001 /* add index string */
5002 proto_item_append_text(psf_entry
," (%s", val_to_str_ext_const(((uint32_t)(sod_index
<<16)), &sod_index_names
, "User Defined"));
5003 proto_item_append_text(psf_entry
,"_%02Xh", (idx
-sod_index
));
5004 if(sod_index
== EPL_SOD_PDO_RX_MAPP
|| sod_index
== EPL_SOD_PDO_TX_MAPP
)
5006 proto_item_append_text(psf_entry
,"_AU64)");
5010 proto_item_append_text(psf_entry
,"_REC)");
5017 /* get subindex offset */
5018 subindex
= tvb_get_uint8(tvb
, dataoffset
);
5019 proto_item_append_text(psf_od_item
, " SubIdx: 0x%02X", subindex
);
5020 psf_item
= proto_tree_add_uint_format(psf_od_item
, hf_epl_asnd_sdo_cmd_data_mapping_subindex
, tvb
, dataoffset
, 1, subindex
,"SubIndex: 0x%02X", subindex
);
5021 subobj
= subobject_lookup(obj
, subindex
);
5022 name
= subobj
? subobj
->info
.name
5023 : val_to_str_ext_const((subindex
|(idx
<<16)), &sod_index_names
, "User Defined");
5024 proto_item_append_text(psf_item
, " (%s)", name
);
5031 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
5033 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%d)", subindex
);
5041 /* each sub request is 4 bytes */
5044 /* calculating the remaining length, based on the current offset */
5045 remlength
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
5048 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d)", objectcnt
);
5054 dissect_epl_sdo_command_read_by_index(struct epl_convo
*convo
, proto_tree
*epl_tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint8_t segmented
, bool response
, uint16_t segment_size
)
5056 int size
, payload_length
, rem_size
= 0;
5057 uint16_t idx
= 0x00;
5058 uint8_t subindex
= 0x00;
5059 uint32_t fragmentId
, frame
;
5060 proto_item
*psf_item
, *cmd_payload
;
5061 proto_tree
*payload_tree
;
5062 bool end_segment
= false;
5063 fragment_head
*frag_msg
= NULL
;
5064 struct object
*obj
= NULL
;
5065 const struct subobject
*subobj
= NULL
;
5066 struct read_req
*req
;
5067 const struct epl_datatype
*type
= NULL
;
5069 /* get the current frame number */
5075 idx
= tvb_get_letohs(tvb
, offset
);
5076 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
5077 obj
= object_lookup(convo
->profile
, idx
);
5079 name
= obj
? obj
->info
.name
: val_to_str_ext_const(((uint32_t)(idx
<<16)), &sod_index_names
, "User Defined");
5080 proto_item_append_text(psf_item
," (%s)", name
);
5084 subindex
= tvb_get_uint8(tvb
, offset
);
5085 psf_item
= proto_tree_add_item(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
5086 subobj
= subobject_lookup(obj
, subindex
);
5088 name
= subobj
? subobj
->info
.name
5089 : val_to_str_ext_const((subindex
|(idx
<<16)), &sod_index_names
, "User Defined");
5090 proto_item_append_text(psf_item
, " (%s)", name
);
5094 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s[%d]: (0x%04X/%d)",
5095 val_to_str_ext(EPL_ASND_SDO_COMMAND_READ_BY_INDEX
, &epl_sdo_asnd_commands_short_ext
, "Command(%02X)"),
5096 segment_size
, idx
, subindex
);
5097 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s", val_to_str_ext_const(((uint32_t) (idx
<< 16)), &sod_index_names
, "User Defined"));
5098 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "/%s)",val_to_str_ext_const((subindex
|(idx
<<16)), &sod_index_names
, "User Defined"));
5100 /* Cache object for read in next response */
5101 req
= convo_read_req_set(convo
, convo
->seq_send
);
5103 req
->subindex
= subindex
;
5106 req
->info
= subobj
? &subobj
->info
: &obj
->info
;
5107 req
->index_name
= obj
->info
.name
;
5112 req
->index_name
= NULL
;
5117 /* upload and no response */
5118 if(segmented
> 0x01 && segment_size
!= 0)
5120 /* get the fragmentId */
5121 fragmentId
= (uint32_t)((((uint32_t)epl_segmentation
.src
)<<16)+epl_segmentation
.dest
);
5122 /* set the fragmented flag */
5123 pinfo
->fragmented
= true;
5124 /* get payload size */
5125 payload_length
= tvb_reported_length_remaining(tvb
, offset
);
5126 /* if the frame is the last frame */
5127 if(segmented
== EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE
)
5130 if(epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == 0x00 ||
5131 epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == frame
)
5133 if (epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == 0x00)
5135 /* store the current frame and increase the counter */
5136 epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] = frame
;
5138 /* add the frame to reassembly_table */
5141 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
5142 fragmentId
, NULL
, 0, payload_length
, end_segment
? false : true );
5143 fragment_add_seq_offset(&epl_reassembly_table
, pinfo
, fragmentId
, NULL
, count
);
5149 frag_msg
= fragment_add_seq_check(&epl_reassembly_table
, tvb
, offset
, pinfo
,
5150 fragmentId
, NULL
, count
, payload_length
, end_segment
? false : true );
5154 /* if the reassembly_table is not Null and the frame stored is the same as the current frame */
5155 if(frag_msg
!= NULL
&& (epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
][epl_segmentation
.send
] == frame
))
5157 if(end_segment
|| payload_length
> 0)
5159 cmd_payload
= proto_tree_add_uint_format(epl_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, offset
, payload_length
,0,
5160 "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg
->len
,payload_length
);
5161 payload_tree
= proto_item_add_subtree(cmd_payload
, ett_epl_asnd_sdo_data_reassembled
);
5162 /* add the reassembly fields */
5163 process_reassembled_data(tvb
, 0, pinfo
, "Reassembled Message", frag_msg
, &epl_frag_items
, NULL
, payload_tree
);
5164 proto_tree_add_uint_format_value(payload_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, 0, 0,
5165 payload_length
, "%d bytes (over all fragments)", frag_msg
->len
);
5166 if (frag_msg
->reassembled_in
== frame
)
5167 col_append_str(pinfo
->cinfo
, COL_INFO
, " (Message Reassembled)" );
5169 memset(&epl_asnd_sdo_reassembly_read
.frame
[epl_segmentation
.recv
], 0, sizeof(uint32_t) * EPL_MAX_SEQUENCE
);
5173 cmd_payload
= proto_tree_add_uint_format(epl_tree
, hf_epl_asnd_sdo_cmd_reassembled
, tvb
, offset
, payload_length
,0,
5174 "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg
->len
,payload_length
);
5175 payload_tree
= proto_item_add_subtree(cmd_payload
, ett_epl_asnd_sdo_data_reassembled
);
5176 /* add reassemble field => Reassembled in: */
5177 process_reassembled_data(tvb
, 0, pinfo
, "Reassembled Message", frag_msg
, &epl_frag_items
, NULL
, payload_tree
);
5183 col_append_str(pinfo
->cinfo
, COL_INFO
, "Response");
5185 size
= tvb_reported_length_remaining(tvb
, offset
);
5187 /* Did we register the read req? */
5189 if ((req
= convo_read_req_get(convo
, pinfo
, convo
->seq_send
)))
5192 ti
= proto_tree_add_uint_format_value(epl_tree
, hf_epl_asnd_sdo_cmd_data_index
, tvb
, 0, 0, req
->idx
, "%04X", req
->idx
);
5193 proto_item_set_generated(ti
);
5196 proto_item_append_text (ti
, " (%s)", req
->index_name
);
5197 type
= req
->info
->type
;
5200 ti
= proto_tree_add_uint_format_value(epl_tree
, hf_epl_asnd_sdo_cmd_data_subindex
, tvb
, 0, 0, req
->subindex
, "%02X", req
->subindex
);
5201 proto_item_set_generated(ti
);
5203 if (req
->info
&& req
->info
->name
!= req
->index_name
)
5204 proto_item_append_text (ti
, " (%s)", req
->info
->name
);
5208 /* determine remaining SDO payload size (depends on segment size of current command) */
5209 if (size
> segment_size
)
5211 rem_size
= segment_size
;
5218 offset
= dissect_epl_payload(epl_tree
, tvb
, pinfo
, offset
, rem_size
, type
, EPL_ASND
);
5224 static struct profile
*profile_load(wmem_allocator_t
*allocator
, const char *path
)
5226 struct profile
*profile
= NULL
;
5228 if (!epl_profile_uat_fld_fileopen_check_cb(NULL
, path
, (unsigned)strlen(path
), NULL
, NULL
, &err
))
5230 report_failure("%s", err
);
5235 if (g_str_has_suffix(path
, ".eds"))
5237 profile
= profile_new(allocator
);
5238 if (!epl_eds_load(profile
, path
))
5239 profile_del(profile
);
5242 else if (g_str_has_suffix(path
, ".xdd") || g_str_has_suffix(path
, ".xdc"))
5244 profile
= profile_new(allocator
);
5245 if (!epl_xdd_load(profile
, path
))
5246 profile_del(profile
);
5250 report_failure("Profile '%s' couldn't be parsed", path
);
5255 static void apply_prefs(void)
5257 /* This gets called for all preferences, so we only load profile if path changes */
5258 if (epl_default_profile_path
!= epl_default_profile_path_last
5259 && epl_default_profile_path
&& *epl_default_profile_path
)
5261 profile_del(epl_default_profile
);
5262 epl_default_profile
= profile_load(wmem_epan_scope(), epl_default_profile_path
);
5264 epl_default_profile_path_last
= epl_default_profile_path
;
5265 /* TODO we could use something like UAT_AFFECTS_DISSECTION */
5270 /* Register the protocol with Wireshark */
5272 proto_register_epl(void)
5274 static hf_register_info hf
[] = {
5275 /* Common data fields (same for all message types) */
5277 { "MessageType", "epl.mtyp",
5278 FT_UINT8
, BASE_DEC
, VALS(mtyp_vals
), 0x7F, NULL
, HFILL
}
5281 { "Node", "epl.node",
5282 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5285 { "Destination", "epl.dest",
5286 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5289 { "Source", "epl.src",
5290 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5292 { &hf_epl_payload_real
,
5293 { "Captured Size", "epl.payload.capture_size",
5294 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5297 /* hotfields for all available EPL message types (depends on EPL MessageType) */
5300 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5303 { "PReq", "epl.preq",
5304 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5307 { "PRes", "epl.pres",
5308 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5312 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5315 { "ASnd", "epl.asnd",
5316 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5319 { "AMNI", "epl.amni",
5320 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5323 { "AInv", "epl.ainv",
5324 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5327 /* SoC data fields*/
5328 { &hf_epl_soc_flags
,
5329 { "Flags", "epl.soc.flags",
5330 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
5333 { "MC (Multiplexed Cycle Completed)", "epl.soc.mc",
5334 FT_BOOLEAN
, 8, NULL
, EPL_SOC_MC_MASK
, NULL
, HFILL
}
5337 { "PS (Prescaled Slot)", "epl.soc.ps",
5338 FT_BOOLEAN
, 8, NULL
, EPL_SOC_PS_MASK
, NULL
, HFILL
}
5340 { &hf_epl_soc_dna_an
,
5341 { "AN (Global)", "epl.soc.an",
5342 FT_BOOLEAN
, 8, NULL
, EPL_SOC_AN_MASK
, NULL
, HFILL
}
5344 { &hf_epl_soc_nettime
,
5345 { "NetTime", "epl.soc.nettime",
5346 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0, NULL
, HFILL
}
5348 { &hf_epl_soc_relativetime
,
5349 { "RelativeTime", "epl.soc.relativetime",
5350 FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
5353 /* PReq data fields*/
5354 { &hf_epl_preq_flags
,
5355 { "Flags", "epl.preq.flags",
5356 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
5359 { "MS (Multiplexed Slot)", "epl.preq.ms",
5360 FT_BOOLEAN
, 8, NULL
, 0x20, NULL
, HFILL
}
5363 { "EA (Exception Acknowledge)", "epl.preq.ea",
5364 FT_BOOLEAN
, 8, NULL
, EPL_PDO_EA_MASK
, NULL
, HFILL
}
5367 { "RD (Ready)", "epl.preq.rd",
5368 FT_BOOLEAN
, 8, NULL
, EPL_PDO_RD_MASK
, NULL
, HFILL
}
5371 { "SLS (Second Link Status)", "epl.preq.sls",
5372 FT_BOOLEAN
, 8, NULL
, EPL_PDO_SLS_MASK
, NULL
, HFILL
}
5375 { "FLS (First Link Status)", "epl.preq.fls",
5376 FT_BOOLEAN
, 8, NULL
, EPL_PDO_FLS_MASK
, NULL
, HFILL
}
5378 { &hf_epl_preq_pdov
,
5379 { "PDOVersion", "epl.preq.pdov",
5380 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(elp_version
), 0x00, NULL
, HFILL
}
5382 { &hf_epl_preq_size
,
5383 { "Size", "epl.preq.size",
5384 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5387 /* PRes data fields*/
5388 { &hf_epl_pres_stat_ms
,
5389 { "NMTStatus", "epl.pres.stat",
5390 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_ms_vals
), 0x00, NULL
, HFILL
}
5392 { &hf_epl_pres_stat_cs
,
5393 { "NMTStatus", "epl.pres.stat",
5394 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_cs_vals
), 0x00, NULL
, HFILL
}
5396 { &hf_epl_pres_flags
,
5397 { "Flags", "epl.pres.flags",
5398 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
5401 { "MS (Multiplexed Slot)", "epl.pres.ms",
5402 FT_BOOLEAN
, 8, NULL
, 0x20, NULL
, HFILL
}
5405 { "EN (Exception New)", "epl.pres.en",
5406 FT_BOOLEAN
, 8, NULL
, EPL_PDO_EN_MASK
, NULL
, HFILL
}
5409 { "RD (Ready)", "epl.pres.rd",
5410 FT_BOOLEAN
, 8, NULL
, EPL_PDO_RD_MASK
, NULL
, HFILL
}
5413 { "PR (Priority)", "epl.pres.pr",
5414 FT_UINT8
, BASE_DEC
, VALS(epl_pr_vals
), 0x38, NULL
, HFILL
}
5417 { "RS (RequestToSend)", "epl.pres.rs",
5418 FT_UINT8
, BASE_DEC
, NULL
, EPL_PDO_RS_MASK
, NULL
, HFILL
}
5421 { "SLS (Second Link Status)", "epl.pres.sls",
5422 FT_BOOLEAN
, 8, NULL
, EPL_PDO_SLS_MASK
, NULL
, HFILL
}
5425 { "FLS (First Link Status)", "epl.pres.fls",
5426 FT_BOOLEAN
, 8, NULL
, EPL_PDO_FLS_MASK
, NULL
, HFILL
}
5428 { &hf_epl_pres_pdov
,
5429 { "PDOVersion", "epl.pres.pdov",
5430 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(elp_version
), 0x00, NULL
, HFILL
}
5432 { &hf_epl_pres_size
,
5433 { "Size", "epl.pres.size",
5434 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5437 /* SoA data fields*/
5438 { &hf_epl_soa_stat_ms
,
5439 { "NMTStatus", "epl.soa.stat",
5440 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_ms_vals
), 0x00, NULL
, HFILL
}
5442 { &hf_epl_soa_stat_cs
,
5443 { "NMTStatus", "epl.soa.stat",
5444 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_cs_vals
), 0x00, NULL
, HFILL
}
5447 { "EA (Exception Acknowledge)", "epl.soa.ea",
5448 FT_BOOLEAN
, 8, NULL
, EPL_SOA_EA_MASK
, NULL
, HFILL
}
5451 { "ER (Exception Reset)", "epl.soa.er",
5452 FT_BOOLEAN
, 8, NULL
, EPL_SOA_ER_MASK
, NULL
, HFILL
}
5455 { "RequestedServiceID", "epl.soa.svid",
5456 FT_UINT8
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(soa_svid_vals
), 0x00, NULL
, HFILL
}
5459 { "RequestedServiceTarget", "epl.soa.svtg",
5460 FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5463 { "EPLVersion", "epl.soa.eplv",
5464 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(elp_version
), 0x00, NULL
, HFILL
}
5466 { &hf_epl_soa_rrflags
,
5467 { "RedundancyFlags", "epl.soa.rrFlags",
5468 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5470 { &hf_epl_soa_rrflags_mnred
,
5471 { "MR - MN Redundancy", "epl.soa.rrFlags.mnred",
5472 FT_BOOLEAN
, 8, TFS(&tfs_active_inactive
), 0x01, NULL
, HFILL
}
5474 { &hf_epl_soa_rrflags_cblred
,
5475 { "CR - Cable Redundancy", "epl.soa.rrFlags.cblred",
5476 FT_BOOLEAN
, 8, TFS(&tfs_active_inactive
), 0x02, NULL
, HFILL
}
5478 { &hf_epl_soa_rrflags_ringred
,
5479 { "RR - Ring Redundancy", "epl.soa.rrFlags.ringred",
5480 FT_BOOLEAN
, 8, TFS(&tfs_active_inactive
), 0x04, NULL
, HFILL
}
5482 { &hf_epl_soa_rrflags_ringstat
,
5483 { "RR - Ring Status", "epl.soa.rrFlags.ringstat",
5484 FT_BOOLEAN
, 8, TFS(&tfs_open_closed
), 0x08, NULL
, HFILL
}
5487 { "SyncControl", "epl.soa.sync",
5488 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5491 { "DestMacAddressValid", "epl.soa.adva",
5492 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_MAC_VALID
, NULL
, HFILL
}
5495 { &hf_epl_soa_pre_tm
,
5496 { "PResFallBackTimeoutValid", "epl.soa.tm",
5497 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_PRES_TIMEOUT
, NULL
, HFILL
}
5499 { &hf_epl_soa_mnd_sec
,
5500 { "SyncMNDelaySecondValid", "epl.soa.mnsc",
5501 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_MND_SECOND
, NULL
, HFILL
}
5503 { &hf_epl_soa_mnd_fst
,
5504 { "SyncMNDelayFirstValid", "epl.soa.mnft",
5505 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_MND_FIRST
, NULL
, HFILL
}
5507 { &hf_epl_soa_pre_sec
,
5508 { "PResTimeSecondValid", "epl.soa.prsc",
5509 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_PRES_SECOND
, NULL
, HFILL
}
5511 { &hf_epl_soa_pre_fst
,
5512 { "PResTimeFirstValid", "epl.soa.prft",
5513 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_PRES_FIRST
, NULL
, HFILL
}
5515 { &hf_epl_soa_pre_set
,
5516 { "PResModeSet", "epl.soa.prmst",
5517 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_PRES_SET
, NULL
, HFILL
}
5519 { &hf_epl_soa_pre_res
,
5520 { "PResModeReset", "epl.soa.prmrst",
5521 FT_BOOLEAN
, 8, NULL
, EPL_SOA_SYNC_PRES_RESET
, NULL
, HFILL
}
5523 { &hf_epl_soa_mac_end
,
5524 { "DestMacAddress", "epl.soa.adva.end",
5525 FT_ETHER
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
5527 { &hf_epl_soa_pre_tm_end
,
5528 { "PResFallBackTimeoutValid", "epl.soa.tm.end",
5529 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5531 { &hf_epl_soa_mnd_sec_end
,
5532 { "SyncMNDelaySecondValid", "epl.soa.mnsc.end",
5533 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5535 { &hf_epl_soa_mnd_fst_end
,
5536 { "SyncMNDelayFirstValid", "epl.soa.mnft.end",
5537 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5539 { &hf_epl_soa_pre_sec_end
,
5540 { "PResTimeSecondValid", "epl.soa.prsc.end",
5541 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5543 { &hf_epl_soa_pre_fst_end
,
5544 { "PResTimeFirstValid", "epl.soa.prft.end",
5545 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5547 { &hf_epl_soa_dna_an_glb
,
5548 { "AN (Global)", "epl.soa.an.global",
5549 FT_BOOLEAN
, 8, NULL
, 0x08, NULL
, HFILL
}
5551 { &hf_epl_soa_dna_an_lcl
,
5552 { "AN (Local)", "epl.soa.an.local",
5553 FT_BOOLEAN
, 8, NULL
, 0x10, NULL
, HFILL
}
5556 { &hf_epl_asnd_svid
,
5557 { "Requested Service ID", "epl.asnd.svid",
5558 FT_UINT8
, BASE_HEX
|BASE_RANGE_STRING
, RVALS(asnd_svid_vals
), 0x00, NULL
, HFILL
}
5560 { &hf_epl_asnd_svtg
,
5561 { "Requested Service Target", "epl.asnd.svtg",
5562 FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5565 { &hf_epl_asnd_data
,
5566 { "Data", "epl.asnd.data",
5567 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5571 /* ASnd-->IdentResponse */
5572 { &hf_epl_asnd_identresponse_en
,
5573 { "EN (Exception New)", "epl.asnd.ires.en",
5574 FT_BOOLEAN
, 8, NULL
, EPL_ASND_EN_MASK
, NULL
, HFILL
}
5576 { &hf_epl_asnd_identresponse_ec
,
5577 { "EC (Exception Clear)", "epl.asnd.ires.ec",
5578 FT_BOOLEAN
, 8, NULL
, EPL_ASND_EC_MASK
, NULL
, HFILL
}
5580 { &hf_epl_asnd_identresponse_pr
,
5581 { "PR (Priority)", "epl.asnd.ires.pr",
5582 FT_UINT8
, BASE_DEC
, VALS(epl_pr_vals
), 0x38, NULL
, HFILL
}
5584 { &hf_epl_asnd_identresponse_rs
,
5585 { "RS (RequestToSend)", "epl.asnd.ires.rs",
5586 FT_UINT8
, BASE_DEC
, NULL
, EPL_ASND_RS_MASK
, NULL
, HFILL
}
5588 { &hf_epl_asnd_identresponse_sls
,
5589 { "SLS (Second Link Status)", "epl.asnd.ires.sls",
5590 FT_BOOLEAN
, 8, NULL
, EPL_ASND_SLS_MASK
, NULL
, HFILL
}
5592 { &hf_epl_asnd_identresponse_fls
,
5593 { "FLS (First Link Status)", "epl.asnd.ires.fls",
5594 FT_BOOLEAN
, 8, NULL
, EPL_ASND_FLS_MASK
, NULL
, HFILL
}
5596 { &hf_epl_asnd_identresponse_stat_ms
,
5597 { "NMTStatus", "epl.asnd.ires.state",
5598 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_ms_vals
), 0x00, NULL
, HFILL
}
5600 { &hf_epl_asnd_identresponse_stat_cs
,
5601 { "NMTStatus", "epl.asnd.ires.state",
5602 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_cs_vals
), 0x00, NULL
, HFILL
}
5604 { &hf_epl_asnd_identresponse_ever
,
5605 { "EPLVersion", "epl.asnd.ires.eplver",
5606 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(elp_version
), 0x00, NULL
, HFILL
}
5608 { &hf_epl_asnd_identresponse_feat
,
5609 { "FeatureFlags", "epl.asnd.ires.features",
5610 FT_UINT32
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5612 { &hf_epl_asnd_identresponse_feat_bit0
,
5613 { "Isochronous", "epl.asnd.ires.features.bit0",
5614 FT_BOOLEAN
, 32, NULL
, 0x00000001, NULL
, HFILL
}
5616 { &hf_epl_asnd_identresponse_feat_bit1
,
5617 { "SDO by UDP/IP", "epl.asnd.ires.features.bit1",
5618 FT_BOOLEAN
, 32, NULL
, 0x00000002, NULL
, HFILL
}
5620 { &hf_epl_asnd_identresponse_feat_bit2
,
5621 { "SDO by ASnd", "epl.asnd.ires.features.bit2",
5622 FT_BOOLEAN
, 32, NULL
, 0x00000004, NULL
, HFILL
}
5624 { &hf_epl_asnd_identresponse_feat_bit3
,
5625 { "SDO by PDO", "epl.asnd.ires.features.bit3",
5626 FT_BOOLEAN
, 32, NULL
, 0x00000008, NULL
, HFILL
}
5628 { &hf_epl_asnd_identresponse_feat_bit4
,
5629 { "NMT Info Services", "epl.asnd.ires.features.bit4",
5630 FT_BOOLEAN
, 32, NULL
, 0x00000010, NULL
, HFILL
}
5632 { &hf_epl_asnd_identresponse_feat_bit5
,
5633 { "Ext. NMT State Commands", "epl.asnd.ires.features.bit5",
5634 FT_BOOLEAN
, 32, NULL
, 0x00000020, NULL
, HFILL
}
5636 { &hf_epl_asnd_identresponse_feat_bit6
,
5637 { "Dynamic PDO Mapping", "epl.asnd.ires.features.bit6",
5638 FT_BOOLEAN
, 32, NULL
, 0x00000040, NULL
, HFILL
}
5640 { &hf_epl_asnd_identresponse_feat_bit7
,
5641 { "NMT Service by UDP/IP", "epl.asnd.ires.features.bit7",
5642 FT_BOOLEAN
, 32, NULL
, 0x00000080, NULL
, HFILL
}
5644 { &hf_epl_asnd_identresponse_feat_bit8
,
5645 { "Configuration Manager", "epl.asnd.ires.features.bit8",
5646 FT_BOOLEAN
, 32, NULL
, 0x00000100, NULL
, HFILL
}
5648 { &hf_epl_asnd_identresponse_feat_bit9
,
5649 { "Multiplexed Access", "epl.asnd.ires.features.bit9",
5650 FT_BOOLEAN
, 32, NULL
, 0x00000200, NULL
, HFILL
}
5652 { &hf_epl_asnd_identresponse_feat_bitA
,
5653 { "NodeID setup by SW", "epl.asnd.ires.features.bitA",
5654 FT_BOOLEAN
, 32, NULL
, 0x00000400, NULL
, HFILL
}
5656 { &hf_epl_asnd_identresponse_feat_bitB
,
5657 { "MN Basic Ethernet Mode", "epl.asnd.ires.features.bitB",
5658 FT_BOOLEAN
, 32, NULL
, 0x00000800, NULL
, HFILL
}
5660 { &hf_epl_asnd_identresponse_feat_bitC
,
5661 { "Routing Type 1 Support", "epl.asnd.ires.features.bitC",
5662 FT_BOOLEAN
, 32, NULL
, 0x00001000, NULL
, HFILL
}
5664 { &hf_epl_asnd_identresponse_feat_bitD
,
5665 { "Routing Type 2 Support", "epl.asnd.ires.features.bitD",
5666 FT_BOOLEAN
, 32, NULL
, 0x00002000, NULL
, HFILL
}
5668 { &hf_epl_asnd_identresponse_feat_bitE
,
5669 { "SDO Read/Write All", "epl.asnd.ires.features.bitE",
5670 FT_BOOLEAN
, 32, NULL
, 0x00004000, NULL
, HFILL
}
5672 { &hf_epl_asnd_identresponse_feat_bitF
,
5673 { "SDO Read/Write Multiple", "epl.asnd.ires.features.bitF",
5674 FT_BOOLEAN
, 32, NULL
, 0x00008000, NULL
, HFILL
}
5676 { &hf_epl_asnd_identresponse_feat_bit10
,
5677 { "Multiple-ASend Support", "epl.asnd.ires.features.bit10",
5678 FT_BOOLEAN
, 32, NULL
, 0x00010000, NULL
, HFILL
}
5680 { &hf_epl_asnd_identresponse_feat_bit11
,
5681 { "Ring Redundancy", "epl.asnd.ires.features.bit11",
5682 FT_BOOLEAN
, 32, NULL
, 0x00020000, NULL
, HFILL
}
5684 { &hf_epl_asnd_identresponse_feat_bit12
,
5685 { "PResChaining", "epl.asnd.ires.features.bit12",
5686 FT_BOOLEAN
, 32, NULL
, 0x00040000, NULL
, HFILL
}
5688 { &hf_epl_asnd_identresponse_feat_bit13
,
5689 { "Multiple PReq/PRes", "epl.asnd.ires.features.bit13",
5690 FT_BOOLEAN
, 32, NULL
, 0x00080000, NULL
, HFILL
}
5692 { &hf_epl_asnd_identresponse_feat_bit14
,
5693 { "Dynamic Node Allocation", "epl.asnd.ires.features.bit14",
5694 FT_BOOLEAN
, 32, NULL
, 0x00100000, NULL
, HFILL
}
5696 { &hf_epl_asnd_identresponse_feat_bit21
,
5697 { "Modular Device", "epl.asnd.ires.features.bit21",
5698 FT_BOOLEAN
, 32, NULL
, 0x00200000, NULL
, HFILL
}
5700 { &hf_epl_asnd_identresponse_mtu
,
5701 { "MTU", "epl.asnd.ires.mtu",
5702 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5704 { &hf_epl_asnd_identresponse_pis
,
5705 { "PollInSize", "epl.asnd.ires.pollinsize",
5706 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5708 { &hf_epl_asnd_identresponse_pos
,
5709 { "PollOutSize", "epl.asnd.ires.polloutsizes",
5710 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5712 { &hf_epl_asnd_identresponse_rst
,
5713 { "ResponseTime", "epl.asnd.ires.resptime",
5714 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5716 { &hf_epl_asnd_identresponse_dt
,
5717 { "DeviceType", "epl.asnd.ires.devicetype",
5718 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5720 { &hf_epl_asnd_identresponse_dt_add
,
5721 { "DeviceType additional info", "epl.asnd.ires.devicetype.add",
5722 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5724 { &hf_epl_asnd_identresponse_profile_path
,
5725 { "Profile Path", "epl.asnd.ires.profilepath",
5726 FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5728 { &hf_epl_asnd_identresponse_vid
,
5729 { "VendorId", "epl.asnd.ires.vendorid",
5730 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5732 { &hf_epl_asnd_identresponse_productcode
,
5733 { "ProductCode", "epl.asnd.ires.productcode",
5734 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5736 { &hf_epl_asnd_identresponse_rno
,
5737 { "RevisionNumber", "epl.asnd.ires.revisionno",
5738 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5740 { &hf_epl_asnd_identresponse_sno
,
5741 { "SerialNumber", "epl.asnd.ires.serialno",
5742 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5744 { &hf_epl_asnd_identresponse_vex1
,
5745 { "VendorSpecificExtension1", "epl.asnd.ires.vendorext1",
5746 FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5748 { &hf_epl_asnd_identresponse_vcd
,
5749 { "VerifyConfigurationDate", "epl.asnd.ires.confdate",
5750 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5752 { &hf_epl_asnd_identresponse_vct
,
5753 { "VerifyConfigurationTime", "epl.asnd.ires.conftime",
5754 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5756 { &hf_epl_asnd_identresponse_ad
,
5757 { "ApplicationSwDate", "epl.asnd.ires.appswdate",
5758 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5760 { &hf_epl_asnd_identresponse_at
,
5761 { "ApplicationSwTime", "epl.asnd.ires.appswtime",
5762 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5764 { &hf_epl_asnd_identresponse_ipa
,
5765 { "IPAddress", "epl.asnd.ires.ip",
5766 FT_IPv4
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5768 { &hf_epl_asnd_identresponse_snm
,
5769 { "SubnetMask", "epl.asnd.ires.subnet",
5770 FT_IPv4
, BASE_NETMASK
, NULL
, 0x00, NULL
, HFILL
}
5772 { &hf_epl_asnd_identresponse_gtw
,
5773 { "DefaultGateway", "epl.asnd.ires.gateway",
5774 FT_IPv4
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5776 { &hf_epl_asnd_identresponse_hn
,
5777 { "HostName", "epl.asnd.ires.hostname",
5778 FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5780 { &hf_epl_asnd_identresponse_vex2
,
5781 { "VendorSpecificExtension2", "epl.asnd.ires.vendorext2",
5782 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5785 /* ASnd-->StatusResponse */
5786 { &hf_epl_asnd_statusresponse_en
,
5787 { "EN (Exception New)", "epl.asnd.sres.en",
5788 FT_BOOLEAN
, 8, NULL
, EPL_ASND_EN_MASK
, NULL
, HFILL
}
5790 { &hf_epl_asnd_statusresponse_ec
,
5791 { "EC (Exception Clear)", "epl.asnd.sres.ec",
5792 FT_BOOLEAN
, 8, NULL
, EPL_ASND_EC_MASK
, NULL
, HFILL
}
5794 { &hf_epl_asnd_statusresponse_pr
,
5795 { "PR (Priority)", "epl.asnd.sres.pr",
5796 FT_UINT8
, BASE_DEC
, VALS(epl_pr_vals
), 0x38, NULL
, HFILL
}
5798 { &hf_epl_asnd_statusresponse_rs
,
5799 { "RS (RequestToSend)", "epl.asnd.sres.rs",
5800 FT_UINT8
, BASE_DEC
, NULL
, EPL_ASND_RS_MASK
, NULL
, HFILL
}
5802 { &hf_epl_asnd_statusresponse_sls
,
5803 { "SLS (Second Link Status)", "epl.asnd.sres.sls",
5804 FT_BOOLEAN
, 8, NULL
, EPL_ASND_SLS_MASK
, NULL
, HFILL
}
5806 { &hf_epl_asnd_statusresponse_fls
,
5807 { "FLS (First Link Status)", "epl.asnd.sres.fls",
5808 FT_BOOLEAN
, 8, NULL
, EPL_ASND_FLS_MASK
, NULL
, HFILL
}
5810 { &hf_epl_asnd_statusresponse_stat_ms
,
5811 { "NMTStatus", "epl.asnd.sres.stat",
5812 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_ms_vals
), 0x00, NULL
, HFILL
}
5814 { &hf_epl_asnd_statusresponse_stat_cs
,
5815 { "NMTStatus", "epl.asnd.sres.stat",
5816 FT_UINT8
, BASE_HEX
, VALS(epl_nmt_cs_vals
), 0x00, NULL
, HFILL
}
5818 /* ASnd-->SyncResponse */
5819 { &hf_epl_asnd_syncResponse_sync
,
5820 { "SyncResponse", "epl.asnd.syncresponse.sync",
5821 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5823 { &hf_epl_asnd_syncResponse_fst_val
,
5824 { "PResTimeFirstValid", "epl.asnd.syncresponse.fst.val",
5825 FT_BOOLEAN
, 8, NULL
, EPL_ASND_SYNCRESPONSE_FST_VALID
, NULL
, HFILL
}
5827 { &hf_epl_asnd_syncResponse_sec_val
,
5828 { "PResTimeSecondValid", "epl.asnd.syncresponse.sec.val",
5829 FT_BOOLEAN
, 8, NULL
, EPL_ASND_SYNCRESPONSE_SEC_VALID
, NULL
, HFILL
}
5831 { &hf_epl_asnd_syncResponse_mode
,
5832 { "PResModeStatus", "epl.asnd.syncresponse.mode",
5833 FT_BOOLEAN
, 8, NULL
, EPL_ASND_SYNCRESPONSE_MODE
, NULL
, HFILL
}
5835 { &hf_epl_asnd_syncResponse_latency
,
5836 { "Latency", "epl.asnd.syncresponse.latency",
5837 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5839 { &hf_epl_asnd_syncResponse_node
,
5840 { "SyncDelayStation", "epl.asnd.syncresponse.delay.station",
5841 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5843 { &hf_epl_asnd_syncResponse_delay
,
5844 { "SyncDelay", "epl.asnd.syncresponse.delay",
5845 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5847 { &hf_epl_asnd_syncResponse_pre_fst
,
5848 { "PResTimeFirst", "epl.asnd.syncresponse.pres.fst",
5849 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5851 { &hf_epl_asnd_syncResponse_pre_sec
,
5852 { "PResTimeSecond", "epl.asnd.syncresponse.pres.sec",
5853 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5856 { &hf_epl_asnd_statusresponse_seb
,
5857 { "StaticErrorBitField", "epl.asnd.sres.seb",
5858 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5862 /*StaticErrorBitField */
5863 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit0
,
5864 { "Generic error", "epl.asnd.res.seb.bit0",
5865 FT_UINT8
, BASE_DEC
, NULL
, 0x01, NULL
, HFILL
}
5867 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit1
,
5868 { "Current", "epl.asnd.res.seb.bit1",
5869 FT_UINT8
, BASE_DEC
, NULL
, 0x02, NULL
, HFILL
}
5871 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit2
,
5872 { "Voltage", "epl.asnd.res.seb.bit2",
5873 FT_UINT8
, BASE_DEC
, NULL
, 0x04, NULL
, HFILL
}
5875 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit3
,
5876 { "Temperature", "epl.asnd.res.seb.bit3",
5877 FT_UINT8
, BASE_DEC
, NULL
, 0x08, NULL
, HFILL
}
5879 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit4
,
5880 { "Communication error", "epl.asnd.res.seb.bit4",
5881 FT_UINT8
, BASE_DEC
, NULL
, 0x10, NULL
, HFILL
}
5883 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit5
,
5884 { "Device Profile Spec", "epl.asnd.res.seb.bit5",
5885 FT_UINT8
, BASE_DEC
, NULL
, 0x20, NULL
, HFILL
}
5887 { &hf_epl_asnd_statusresponse_seb_err_errorregister_u8_bit7
,
5888 { "Manufacturer Spec", "epl.asnd.res.seb.bit7",
5889 FT_UINT8
, BASE_DEC
, NULL
, 0x80, NULL
, HFILL
}
5891 { &hf_epl_asnd_statusresponse_seb_devicespecific_err
,
5892 { "Device Profile Spec", "epl.asnd.res.seb.devicespecific_err",
5893 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5897 { &hf_epl_asnd_statusresponse_el
,
5898 { "ErrorCodesList", "epl.asnd.sres.el",
5899 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5901 { &hf_epl_asnd_statusresponse_el_entry
,
5902 { "Entry", "epl.asnd.sres.el.entry",
5903 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5907 /*List of Errors/Events*/
5908 { &hf_epl_asnd_statusresponse_el_entry_type
,
5909 { "Entry Type", "epl.asnd.sres.el.entry.type",
5910 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
5912 { &hf_epl_asnd_statusresponse_el_entry_type_profile
,
5913 { "Profile", "epl.asnd.sres.el.entry.type.profile",
5914 FT_UINT16
, BASE_DEC
, NULL
, 0x0FFF, NULL
, HFILL
}
5916 { &hf_epl_asnd_statusresponse_el_entry_type_mode
,
5917 { "Mode", "epl.asnd.sres.el.entry.type.mode",
5918 FT_UINT16
, BASE_DEC
, NULL
, 0x3000, NULL
, HFILL
}
5920 { &hf_epl_asnd_statusresponse_el_entry_type_bit14
,
5921 { "Bit14", "epl.asnd.sres.el.entry.type.bit14",
5922 FT_UINT16
, BASE_DEC
, NULL
, 0x4000, NULL
, HFILL
}
5924 { &hf_epl_asnd_statusresponse_el_entry_type_bit15
,
5925 { "Bit15", "epl.asnd.sres.el.entry.type.bit15",
5926 FT_UINT16
, BASE_DEC
, NULL
, 0x8000, NULL
, HFILL
}
5928 { &hf_epl_asnd_statusresponse_el_entry_code
,
5929 { "Error Code", "epl.asnd.sres.el.entry.code",
5930 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
5931 &errorcode_vals_ext
, 0x00, NULL
, HFILL
}
5933 { &hf_epl_asnd_statusresponse_el_entry_time
,
5934 { "Time Stamp", "epl.asnd.sres.el.entry.time",
5935 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x00, NULL
, HFILL
}
5937 { &hf_epl_asnd_statusresponse_el_entry_add
,
5938 { "Additional Information", "epl.asnd.sres.el.entry.add",
5939 FT_UINT64
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
5943 /* ASnd-->NMTRequest */
5944 { &hf_epl_asnd_nmtrequest_rcid
,
5945 { "NMTRequestedCommandID", "epl.asnd.nmtrequest.rcid",
5946 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x00, NULL
, HFILL
}
5948 { &hf_epl_asnd_nmtrequest_rct
,
5949 { "NMTRequestedCommandTarget", "epl.asnd.nmtrequest.rct",
5950 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5952 { &hf_epl_asnd_nmtrequest_rcd
,
5953 { "NMTRequestedCommandData", "epl.asnd.nmtrequest.rcd",
5954 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5957 /* ASnd-->NMTCommand */
5958 { &hf_epl_asnd_nmtcommand_cid
,
5959 { "NMTCommandId", "epl.asnd.nmtcommand.cid",
5960 FT_UINT8
, BASE_HEX_DEC
| BASE_EXT_STRING
,
5961 &asnd_cid_vals_ext
, 0x00, NULL
, HFILL
}
5963 { &hf_epl_asnd_nmtcommand_resetnode_reason
,
5964 { "Reset Reason", "epl.asnd.nmtcommand.resetnode_reason",
5965 FT_UINT16
, BASE_HEX
| BASE_EXT_STRING
,
5966 &errorcode_vals_ext
, 0x00, NULL
, HFILL
}
5968 { &hf_epl_asnd_nmtcommand_cdat
,
5969 { "NMTCommandData", "epl.asnd.nmtcommand.cdat",
5970 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5973 { &hf_epl_asnd_nmtcommand_nmtnethostnameset_hn
,
5974 { "HostName", "epl.asnd.nmtcommand.nmtnethostnameset.hn",
5975 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5977 { &hf_epl_asnd_nmtcommand_nmtflusharpentry_nid
,
5978 { "NodeID", "epl.asnd.nmtcommand.nmtflusharpentry.nid",
5979 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}
5981 { &hf_epl_asnd_nmtcommand_nmtpublishtime_dt
,
5982 { "DateTime", "epl.asnd.nmtcommand.nmtpublishtime.dt",
5983 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5985 { &hf_epl_asnd_nmtcommand_nmtdna
,
5986 { "DNA", "epl.asnd.nmtcommand.dna",
5987 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
5989 { &hf_epl_asnd_nmtcommand_nmtdna_flags
,
5990 { "Valid flags", "epl.asnd.nmtcommand.dna.flags",
5991 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
5993 { &hf_epl_asnd_nmtcommand_nmtdna_ltv
,
5994 { "Lease time valid", "epl.asnd.nmtcommand.dna.ltv",
5995 FT_BOOLEAN
, 8, NULL
, 0x10, NULL
, HFILL
}
5997 { &hf_epl_asnd_nmtcommand_nmtdna_hpm
,
5998 { "Hub port enable mask valid", "epl.asnd.nmtcommand.dna.hpm",
5999 FT_BOOLEAN
, 8, NULL
, 0x08, NULL
, HFILL
}
6001 { &hf_epl_asnd_nmtcommand_nmtdna_nnn
,
6002 { "Set new node number", "epl.asnd.nmtcommand.dna.nnn",
6003 FT_BOOLEAN
, 8, NULL
, 0x04, NULL
, HFILL
}
6005 { &hf_epl_asnd_nmtcommand_nmtdna_mac
,
6006 { "Compare current MAC ID", "epl.asnd.nmtcommand.dna.mac",
6007 FT_BOOLEAN
, 8, NULL
, 0x02, NULL
, HFILL
}
6009 { &hf_epl_asnd_nmtcommand_nmtdna_cnn
,
6010 { "Compare current node number", "epl.asnd.nmtcommand.dna.cnn",
6011 FT_BOOLEAN
, 8, NULL
, 0x01, NULL
, HFILL
}
6013 { &hf_epl_asnd_nmtcommand_nmtdna_currmac
,
6014 { "Current MAC ID", "epl.asnd.nmtcommand.dna.currmac",
6015 FT_ETHER
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
6017 { &hf_epl_asnd_nmtcommand_nmtdna_hubenmsk
,
6018 { "Hub port enable mask", "epl.asnd.nmtcommand.dna.hubenmsk",
6019 FT_UINT64
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6021 { &hf_epl_asnd_nmtcommand_nmtdna_currnn
,
6022 { "Current node number", "epl.asnd.nmtcommand.dna.currnn",
6023 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6025 { &hf_epl_asnd_nmtcommand_nmtdna_newnn
,
6026 { "New node number", "epl.asnd.nmtcommand.dna.newnn",
6027 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6029 { &hf_epl_asnd_nmtcommand_nmtdna_leasetime
,
6030 { "Lease Time", "epl.asnd.nmtcommand.dna.leasetime",
6031 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6035 { &hf_epl_asnd_sdo_seq
,
6036 { "Sequence Layer", "epl.asnd.sdo.seq",
6037 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6039 { &hf_epl_asnd_sdo_seq_receive_sequence_number
,
6040 { "ReceiveSequenceNumber", "epl.asnd.sdo.seq.receive.sequence.number",
6041 FT_UINT8
, BASE_DEC
, NULL
, 0xfc, NULL
, HFILL
}
6043 { &hf_epl_asnd_sdo_seq_receive_con
,
6044 { "ReceiveCon", "epl.asnd.sdo.seq.receive.con",
6046 VALS(epl_sdo_receive_con_vals
), 0x03, NULL
, HFILL
}
6048 { &hf_epl_asnd_sdo_seq_send_sequence_number
,
6049 { "SendSequenceNumber", "epl.asnd.sdo.seq.send.sequence.number",
6050 FT_UINT8
, BASE_DEC
, NULL
, 0xfc, NULL
, HFILL
}
6052 { &hf_epl_asnd_sdo_seq_send_con
,
6053 { "SendCon", "epl.asnd.sdo.seq.send.con",
6054 FT_UINT8
, BASE_DEC
, VALS(epl_sdo_send_con_vals
),
6057 { &hf_epl_asnd_sdo_cmd_transaction_id
,
6058 { "SDO Transaction ID", "epl.asnd.sdo.cmd.transaction.id",
6059 FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6061 { &hf_epl_asnd_sdo_cmd_response
,
6062 { "SDO Response", "epl.asnd.sdo.cmd.response",
6064 VALS(epl_sdo_asnd_cmd_response
), 0x80, NULL
, HFILL
}
6067 { &hf_epl_asnd_sdo_resp_in
,
6068 { "Response frame", "epl.asnd.sdo.resp_in",
6069 FT_FRAMENUM
, BASE_NONE
,
6070 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
6071 "The frame number of the corresponding response", HFILL
}
6073 { &hf_epl_asnd_sdo_no_resp
,
6074 { "No response seen", "epl.asnd.sdo.no_resp",
6077 "No corresponding response frame was seen", HFILL
}
6079 { &hf_epl_asnd_sdo_resp_to
,
6080 { "Request frame", "epl.asnd.sdo.resp_to",
6081 FT_FRAMENUM
, BASE_NONE
,
6082 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
6083 "The frame number of the corresponding request", HFILL
}
6086 { &hf_epl_asnd_sdo_cmd
,
6087 { "Command Layer", "epl.asnd.sdo.cmd",
6088 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6090 { &hf_epl_asnd_sdo_cmd_abort
,
6091 { "SDO Abort", "epl.asnd.sdo.cmd.abort",
6093 VALS(epl_sdo_asnd_cmd_abort
), 0x40, NULL
, HFILL
}
6095 { &hf_epl_asnd_sdo_cmd_sub_abort
,
6096 { "SDO Sub Transfer", "epl.asnd.sdo.cmd.sub.abort",
6098 VALS(epl_sdo_asnd_cmd_abort
), 0x80, NULL
, HFILL
}
6100 { &hf_epl_asnd_sdo_cmd_segmentation
,
6101 { "SDO Segmentation", "epl.asnd.sdo.cmd.segmentation",
6103 VALS(epl_sdo_asnd_cmd_segmentation
), 0x30, NULL
, HFILL
}
6105 { &hf_epl_asnd_sdo_cmd_command_id
,
6106 { "SDO Command ID", "epl.asnd.sdo.cmd.command.id",
6107 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
,
6108 &epl_sdo_asnd_commands_ext
, 0x00, NULL
, HFILL
}
6110 { &hf_epl_asnd_sdo_cmd_segment_size
,
6111 { "SDO Segment size", "epl.asnd.sdo.cmd.segment.size",
6112 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6114 { &hf_epl_asnd_sdo_cmd_data_size
,
6115 { "SDO Data size", "epl.asnd.sdo.cmd.data.size",
6116 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6118 { &hf_epl_asnd_sdo_cmd_data_padding
,
6119 { "SDO Data Padding", "epl.asnd.sdo.cmd.data.padding",
6120 FT_UINT8
, BASE_DEC
, NULL
, 0x03, NULL
, HFILL
}
6122 { &hf_epl_asnd_sdo_cmd_abort_code
,
6123 { "SDO Transfer Abort", "epl.asnd.sdo.cmd.abort.code",
6124 FT_UINT32
, BASE_HEX
| BASE_EXT_STRING
,
6125 &sdo_cmd_abort_code_ext
, 0x00, NULL
, HFILL
}
6127 { &hf_epl_asnd_sdo_cmd_data_index
,
6128 { "OD Index", "epl.asnd.sdo.cmd.data.index",
6129 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6131 { &hf_epl_asnd_sdo_cmd_data_subindex
,
6132 { "OD SubIndex", "epl.asnd.sdo.cmd.data.subindex",
6133 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6135 { &hf_epl_asnd_sdo_cmd_data_mapping
,
6136 { "Mapping", "epl.asnd.sdo.cmd.data.mapping",
6137 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6139 { &hf_epl_asnd_sdo_cmd_data_mapping_index
,
6140 { "Index", "epl.asnd.sdo.cmd.data.mapping.index",
6141 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6143 { &hf_epl_asnd_sdo_cmd_data_mapping_subindex
,
6144 { "SubIndex", "epl.asnd.sdo.cmd.data.mapping.subindex",
6145 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6147 { &hf_epl_asnd_sdo_cmd_data_mapping_offset
,
6148 { "Offset", "epl.asnd.sdo.cmd.data.mapping.offset",
6149 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6151 { &hf_epl_asnd_sdo_cmd_data_mapping_length
,
6152 { "Length", "epl.asnd.sdo.cmd.data.mapping.length",
6153 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6155 { &hf_epl_fragments
,
6156 { "Message fragments", "epl.asnd.sdo.cmd.fragments",
6157 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6160 { "Message fragment", "epl.asnd.sdo.cmd.fragment",
6161 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6163 { &hf_epl_fragment_overlap
,
6164 { "Message fragment overlap", "epl.asnd.sdo.cmd.fragment.overlap",
6165 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6167 { &hf_epl_fragment_overlap_conflicts
,
6168 { "Message fragment overlapping with conflicting data",
6169 "epl.asnd.sdo.cmd.fragment.overlap.conflicts",
6170 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6172 { &hf_epl_fragment_multiple_tails
,
6173 { "Message has multiple tail fragments", "epl.asnd.sdo.cmd.fragment.multiple_tails",
6174 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6176 { &hf_epl_fragment_too_long_fragment
,
6177 { "Message fragment too long", "epl.asnd.sdo.cmd.fragment.too_long_fragment",
6178 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6180 { &hf_epl_fragment_error
,
6181 { "Message defragmentation error", "epl.asnd.sdo.cmd.fragment.error",
6182 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6184 { &hf_epl_fragment_count
,
6185 { "Message fragment count", "epl.asnd.sdo.cmd.fragment.count",
6186 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6188 { &hf_epl_asnd_sdo_cmd_reassembled
,
6189 { "Reassembled", "epl.asnd.sdo.cmd.reassembled",
6190 FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6192 { &hf_epl_reassembled_in
,
6193 { "Reassembled in", "epl.asnd.sdo.cmd.reassembled.in",
6194 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6196 { &hf_epl_reassembled_length
,
6197 { "Reassembled length", "epl.asnd.sdo.cmd.reassembled.length",
6198 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6200 { &hf_epl_reassembled_data
,
6201 { "Reassembled Data", "epl.asnd.sdo.cmd.reassembled.data",
6202 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6204 { &hf_epl_sdo_multi_param_sub_abort
,
6205 { "Sub Abort Code", "epl.asnd.sdo.od.multiparam.abort",
6206 FT_UINT32
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6209 /* EPL Data types */
6212 FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6214 { &hf_epl_pdo_index
,
6215 { "Index", "epl.pdo.index",
6216 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6218 { &hf_epl_pdo_subindex
,
6219 { "SubIndex", "epl.pdo.subindex",
6220 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6223 { "PDO meta info", "epl.od.meta",
6224 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6226 { &hf_epl_od_meta_mapping_index
,
6227 { "Mapped by index", "epl.od.meta.index",
6228 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6230 { &hf_epl_od_meta_mapping_subindex
,
6231 { "Mapped by subindex", "epl.od.meta.subindex",
6232 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6234 { &hf_epl_od_meta_lifetime_start
,
6235 { "Lifetime start", "epl.od.meta.lifetime.start",
6236 FT_FRAMENUM
, FT_NONE
, NULL
, 0x00, NULL
, HFILL
}
6238 { &hf_epl_od_meta_lifetime_end
,
6239 { "Lifetime end", "epl.od.meta.lifetime.end",
6240 FT_FRAMENUM
, FT_NONE
, NULL
, 0x00, NULL
, HFILL
}
6242 { &hf_epl_od_meta_offset
,
6243 { "Offset", "epl.od.meta.offset",
6244 FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}
6246 { &hf_epl_od_meta_length
,
6247 { "Length", "epl.od.meta.length",
6248 FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6250 { &hf_epl_od_boolean
,
6251 { "Data", "epl.od.data.boolean",
6252 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6255 { "Data", "epl.od.data.int",
6256 FT_INT64
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6259 { "Data", "epl.od.data.uint",
6260 /* We can't use BASE_DEC_HEX directly, because a FT_UINT8
6261 * would then have 15 leading zeroes */
6262 FT_UINT64
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
6265 { "Data", "epl.od.data.real",
6266 FT_FLOAT
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6268 { &hf_epl_od_string
,
6269 { "Data", "epl.od.data.string",
6270 FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6272 { &hf_epl_od_octet_string
,
6273 { "Data", "epl.od.data.bytestring",
6274 FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6277 { "Data", "epl.od.data.ethaddr",
6278 FT_ETHER
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6281 { "Data", "epl.od.data.ipv4",
6282 FT_IPv4
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6285 { &hf_epl_od_domain
,
6286 { "Data", "epl.od.data.domain",
6287 FT_BYTES
, BASE_ALLOW_ZERO
, NULL
, 0x00, NULL
, HFILL
}
6290 { &hf_epl_od_time_difference
, /* not 1:1 */
6291 { "Data", "epl.od.data.time",
6292 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}
6296 { "Data", "epl.od.data.time",
6297 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0, NULL
, HFILL
}
6301 /* Setup protocol subtree array */
6302 static int *ett
[] = {
6311 &ett_epl_el_entry_type
,
6312 &ett_epl_sdo_entry_type
,
6315 &ett_epl_asnd_sdo_cmd_data_mapping
,
6316 &ett_epl_sdo_sequence_layer
,
6317 &ett_epl_sdo_command_layer
,
6322 &ett_epl_asnd_sdo_data_reassembled
,
6323 &ett_epl_asnd_nmt_dna
,
6327 static ei_register_info ei
[] = {
6328 { &ei_duplicated_frame
,
6329 { "epl.asnd.sdo.duplication", PI_PROTOCOL
, PI_NOTE
,
6330 "Duplicated Frame", EXPFILL
}
6332 { &ei_recvseq_value
,
6333 { "epl.error.value.receive.sequence", PI_PROTOCOL
, PI_ERROR
,
6334 "Invalid Value for ReceiveSequenceNumber", EXPFILL
}
6336 { &ei_sendseq_value
,
6337 { "epl.error.value.send.sequence", PI_PROTOCOL
, PI_ERROR
,
6338 "Invalid Value for SendSequenceNumber", EXPFILL
}
6340 { &ei_real_length_differs
,
6341 { "epl.error.payload.length.differs", PI_PROTOCOL
, PI_ERROR
,
6342 "Captured length differs from header information", EXPFILL
}
6346 module_t
*epl_module
;
6347 expert_module_t
*expert_epl
;
6349 /* Register the protocol name and description */
6350 proto_epl
= proto_register_protocol("Ethernet POWERLINK", "EPL", "epl");
6352 /* subdissector code */
6353 heur_epl_subdissector_list
= register_heur_dissector_list_with_description("epl", "Data encapsulated in EPL", proto_epl
);
6354 heur_epl_data_subdissector_list
= register_heur_dissector_list_with_description("epl_data", "EPL Data", proto_epl
);
6355 epl_asnd_dissector_table
= register_dissector_table("epl.asnd",
6356 "Manufacturer specific ASND service", proto_epl
, FT_UINT8
, BASE_DEC
/*, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE*/);
6358 /* Registering protocol to be called by another dissector */
6359 epl_handle
= register_dissector("epl", dissect_epl
, proto_epl
);
6360 epl_udp_handle
= register_dissector("epl.udp", dissect_epludp
, proto_epl
);
6362 /* Required function calls to register the header fields and subtrees used */
6363 proto_register_field_array(proto_epl
, hf
, array_length(hf
));
6365 proto_register_subtree_array(ett
, array_length(ett
));
6367 /* Register expert information field */
6368 expert_epl
= expert_register_protocol ( proto_epl
);
6369 expert_register_field_array ( expert_epl
, ei
, array_length (ei
) );
6371 /* register preferences */
6372 epl_module
= prefs_register_protocol(proto_epl
, apply_prefs
);
6374 prefs_register_bool_preference(epl_module
, "show_soc_flags", "Show flags of SoC frame in Info column",
6375 "If you are capturing in networks with multiplexed or slow nodes, this can be useful", &show_soc_flags
);
6377 prefs_register_bool_preference(epl_module
, "show_duplicated_command_layer", "Show command-layer in duplicated frames",
6378 "For analysis purposes one might want to show the command layer even if the dissector assumes a duplicated frame", &show_cmd_layer_for_duplicated
);
6380 prefs_register_bool_preference(epl_module
, "show_pdo_meta_info", "Show life times and origin PDO Tx/Rx params for PDO entries",
6381 "For analysis purposes one might want to see how long the current mapping has been active for and what OD write caused it", &show_pdo_meta_info
);
6383 prefs_register_bool_preference(epl_module
, "use_sdo_mappings", "Use SDO ObjectMappings for PDO dissection",
6384 "Partition PDOs according to ObjectMappings sent via SDO", &use_sdo_mappings
);
6387 prefs_register_bool_preference(epl_module
, "use_xdc_mappings", "Use XDC ObjectMappings for PDO dissection",
6388 "If you want to parse the defaultValue (XDD) and actualValue (XDC) attributes for ObjectMappings in order to detect default PDO mappings, which may not be sent over SDO ", &use_xdc_mappings
);
6391 prefs_register_bool_preference(epl_module
, "interpret_untyped_as_le", "Interpret short (<64bit) data as little endian integers",
6392 "If a data field has untyped data under 8 byte long, interpret it as unsigned little endian integer and show decimal and hexadecimal representation thereof. Otherwise use stock data dissector", &interpret_untyped_as_le
);
6394 /* init device profiles support */
6395 epl_profiles_by_device
= wmem_map_new(wmem_epan_scope(), g_direct_hash
, g_direct_equal
);
6396 epl_profiles_by_nodeid
= wmem_map_new(wmem_epan_scope(), g_direct_hash
, g_direct_equal
);
6397 epl_profiles_by_address
= wmem_map_new(wmem_epan_scope(), epl_address_hash
, epl_address_equal
);
6401 prefs_register_filename_preference(epl_module
, "default_profile", "Default Profile to use if no specific profiles exist",
6402 "If you have a capture without IdentResponse and many nodes, it's easier to set a default profile here than to add entries for all MAC address or Node IDs",
6403 &epl_default_profile_path
, false);
6405 device_profile_uat
= uat_new("Device-Specific Profiles",
6406 sizeof (struct device_profile_uat_assoc
),
6407 "epl_device_profiles", /* filename */
6408 true, /* from_profile */
6409 &device_profile_list_uats
, /* data_ptr */
6410 &ndevice_profile_uat
, /* numitems_ptr */
6411 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
6412 NULL
, /* Help section (currently a wiki page) */
6413 device_profile_uat_copy_cb
,
6414 device_profile_uat_update_record
,
6415 device_profile_uat_free_cb
,
6416 device_profile_parse_uat
,
6418 device_profile_list_uats_flds
);
6420 prefs_register_uat_preference(epl_module
, "device_profiles",
6421 "Device-Specific Profiles",
6422 "Add vendor-provided EDS" IF_LIBXML("/XDD") " profiles here",
6427 nodeid_profile_uat
= uat_new("NodeID-Specific Profiles",
6428 sizeof (struct nodeid_profile_uat_assoc
),
6429 "epl_nodeid_profiles", /* filename */
6430 true, /* from_profile */
6431 &nodeid_profile_list_uats
, /* data_ptr */
6432 &nnodeid_profile_uat
, /* numitems_ptr */
6433 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
6434 NULL
, /* Help section (currently a wiki page) */
6435 nodeid_profile_uat_copy_cb
,
6436 nodeid_profile_uat_update_record
,
6437 nodeid_profile_uat_free_cb
,
6438 nodeid_profile_parse_uat
,
6440 nodeid_profile_list_uats_flds
);
6442 prefs_register_uat_preference(epl_module
, "nodeid_profiles",
6443 "Node-Specific Profiles",
6444 "Assign vendor-provided EDS" IF_LIBXML("/XDD") " profiles to CN IDs here",
6448 /* tap-registration */
6449 /* epl_tap = register_tap("epl");*/
6453 proto_reg_handoff_epl(void)
6455 dissector_add_uint("ethertype", ETHERTYPE_EPL_V2
, epl_handle
);
6456 dissector_add_uint_with_preference("udp.port", UDP_PORT_EPL
, epl_udp_handle
);
6459 /* register frame init routine */
6460 register_init_routine( setup_dissector
);
6461 register_cleanup_routine( cleanup_dissector
);
6462 /* register reassembly table */
6463 reassembly_table_register(&epl_reassembly_table
, &addresses_reassembly_table_functions
);
6468 epl_uat_fld_uint16dec_check_cb(void *_record _U_
, const char *str
, unsigned len _U_
, const void *chk_data _U_
, const void *fld_data _U_
, char **err
)
6471 if (!ws_strtou16(str
, NULL
, &val
))
6473 *err
= g_strdup("Invalid argument. Expected a decimal between [0-65535]");
6480 epl_uat_fld_uint32hex_check_cb(void *_record _U_
, const char *str
, unsigned len _U_
, const void *chk_data _U_
, const void *fld_data _U_
, char **err
)
6483 if (!ws_hexstrtou32(str
, NULL
, &val
))
6485 *err
= g_strdup("Invalid argument. Expected a hexadecimal between [0-ffffffff]");
6492 epl_profile_uat_fld_fileopen_check_cb(void *record _U_
, const char *path
, unsigned len
, const void *chk_data _U_
, const void *fld_data _U_
, char **err
)
6494 const char *supported
= "Only" IF_LIBXML(" *.xdd, *.xdc and") " *.eds profiles supported.";
6500 *err
= g_strdup("No filename given.");
6504 if (ws_stat64(path
, &st
) != 0)
6506 *err
= ws_strdup_printf("File '%s' does not exist or access was denied.", path
);
6511 if (g_str_has_suffix(path
, ".eds"))
6517 if (g_str_has_suffix(path
, ".xdd") || g_str_has_suffix(path
, ".xdc"))
6523 *err
= ws_strdup_printf("*.xdd and *.xdc support not compiled in. %s", supported
);
6528 *err
= g_strdup(supported
);
6534 drop_profiles(void *key _U_
, void *value
, void *user_data _U_
)
6536 struct profile
*head
= (struct profile
*)value
, *curr
;
6537 while ((curr
= head
))
6545 device_profile_parse_uat(void)
6548 struct profile
*profile
= NULL
;
6549 wmem_map_foreach(epl_profiles_by_device
, drop_profiles
, NULL
);
6551 /* PDO Mappings will have stale pointers after a profile change
6552 * so we reset the memory pool. As PDO Mappings are referenced
6553 * via Conversations, we need to fixup those too to avoid a use
6554 * after free, preferably by clearing them.
6555 * This generation++ is a temporary workaround
6559 if (pdo_mapping_scope
)
6561 wmem_free_all(pdo_mapping_scope
);
6562 current_convo_generation
++; /* FIXME remove */
6565 for (i
= 0; i
< ndevice_profile_uat
; i
++)
6567 struct device_profile_uat_assoc
*uat
= &(device_profile_list_uats
[i
]);
6569 profile
= (struct profile
*)wmem_map_lookup(epl_profiles_by_device
, GUINT_TO_POINTER(uat
->device_type
));
6571 /* do a shallow copy, we can't use the original because we need different
6572 * ->next pointer for each. May be we should've used Glib's non-intrusive
6573 * linked list to begin with
6577 struct profile
*clone
= wmem_new0(profile
->scope
, struct profile
);
6583 profile
= profile_load(wmem_epan_scope(), uat
->path
);
6588 struct profile
*profile_head
;
6589 if ((profile_head
= (struct profile
*)wmem_map_lookup(epl_profiles_by_device
, GUINT_TO_POINTER(profile
->id
))))
6591 wmem_map_remove(epl_profiles_by_device
, GUINT_TO_POINTER(profile_head
->id
));
6592 profile
->next
= profile_head
;
6595 profile
->id
= uat
->device_type
;
6596 profile
->data
= GUINT_TO_POINTER(profile
->id
);
6597 profile
->vendor_id
= uat
->vendor_id
;
6598 profile
->product_code
= uat
->product_code
;
6600 wmem_map_insert(epl_profiles_by_device
, GUINT_TO_POINTER(profile
->id
), profile
);
6601 profile
->parent_map
= epl_profiles_by_device
;
6603 ws_log(NULL
, LOG_LEVEL_INFO
, "Loading %s\n", profile
->path
);
6608 device_profile_uat_update_record(void *_record _U_
, char **err _U_
)
6614 device_profile_uat_free_cb(void *_r
)
6616 struct device_profile_uat_assoc
*r
= (struct device_profile_uat_assoc
*)_r
;
6621 device_profile_uat_copy_cb(void *dst_
, const void *src_
, size_t len _U_
)
6623 const struct device_profile_uat_assoc
*src
= (const struct device_profile_uat_assoc
*)src_
;
6624 struct device_profile_uat_assoc
*dst
= (struct device_profile_uat_assoc
*)dst_
;
6626 dst
->path
= g_strdup(src
->path
);
6627 dst
->device_type
= src
->device_type
;
6628 dst
->vendor_id
= src
->vendor_id
;
6629 dst
->product_code
= src
->product_code
;
6635 nodeid_profile_parse_uat(void)
6638 struct profile
*profile
= NULL
;
6639 wmem_map_foreach(epl_profiles_by_nodeid
, drop_profiles
, NULL
);
6640 wmem_map_foreach(epl_profiles_by_address
, drop_profiles
, NULL
);
6643 /* PDO Mappings will have stale pointers after a profile change
6644 * so we reset the memory pool. As PDO Mappings are referenced
6645 * via Conversations, we need to fixup those too to avoid a use
6646 * after free, preferably by clearing them.
6647 * This generation++ is a temporary workaround
6650 if (pdo_mapping_scope
)
6652 wmem_free_all(pdo_mapping_scope
);
6653 current_convo_generation
++; /* FIXME remove */
6656 for (i
= 0; i
< nnodeid_profile_uat
; i
++)
6658 struct nodeid_profile_uat_assoc
*uat
= &(nodeid_profile_list_uats
[i
]);
6660 profile
= uat
->is_nodeid
? (struct profile
*)wmem_map_lookup(epl_profiles_by_nodeid
, GUINT_TO_POINTER(uat
->node
.id
))
6661 : (struct profile
*)wmem_map_lookup(epl_profiles_by_address
, &uat
->node
.addr
);
6664 profile
= profile_load(wmem_epan_scope(), uat
->path
);
6671 profile
->nodeid
= uat
->node
.id
;
6672 profile
->data
= GUINT_TO_POINTER(profile
->nodeid
);
6674 wmem_map_insert(epl_profiles_by_nodeid
, GUINT_TO_POINTER(profile
->nodeid
), profile
);
6675 profile
->parent_map
= epl_profiles_by_nodeid
;
6680 copy_address_wmem(profile
->scope
, &profile
->node_addr
, &uat
->node
.addr
);
6681 profile
->data
= &profile
->node_addr
;
6683 wmem_map_insert(epl_profiles_by_address
, &profile
->node_addr
, profile
);
6684 profile
->parent_map
= epl_profiles_by_address
;
6686 ws_log(NULL
, LOG_LEVEL_INFO
, "Loading %s\n", profile
->path
);
6692 nodeid_profile_uat_update_record(void *_record _U_
, char **err _U_
)
6698 nodeid_profile_uat_free_cb(void *_r
)
6700 struct nodeid_profile_uat_assoc
*r
= (struct nodeid_profile_uat_assoc
*)_r
;
6702 free_address(&r
->node
.addr
);
6707 nodeid_profile_uat_copy_cb(void *dst_
, const void *src_
, size_t len _U_
)
6709 const struct nodeid_profile_uat_assoc
*src
= (const struct nodeid_profile_uat_assoc
*)src_
;
6710 struct nodeid_profile_uat_assoc
*dst
= (struct nodeid_profile_uat_assoc
*)dst_
;
6712 dst
->path
= g_strdup(src
->path
);
6713 dst
->id_str
= g_strdup(src
->id_str
);
6714 if ((dst
->is_nodeid
= src
->is_nodeid
))
6715 dst
->node
.id
= src
->node
.id
;
6717 copy_address(&dst
->node
.addr
, &src
->node
.addr
);
6723 nodeid_profile_list_uats_nodeid_tostr_cb(void *_rec
, char **out_ptr
, unsigned *out_len
, const void *u1 _U_
, const void *u2 _U_
)
6725 struct nodeid_profile_uat_assoc
*rec
= (struct nodeid_profile_uat_assoc
*)_rec
;
6728 *out_ptr
= g_strdup(rec
->id_str
);
6729 *out_len
= (unsigned)strlen(rec
->id_str
);
6733 *out_ptr
= g_strdup("");
6739 epl_uat_fld_cn_check_cb(void *record _U_
, const char *str
, unsigned len _U_
, const void *u1 _U_
, const void *u2 _U_
, char **err
)
6743 if (ws_strtou8(str
, NULL
, &nodeid
) && EPL_IS_CN_NODEID(nodeid
))
6746 GByteArray
*addr
= g_byte_array_new();
6748 if (hex_str_to_bytes(str
, addr
, false) && addr
->len
== FT_ETHER_LEN
) {
6749 g_byte_array_free(addr
, true);
6753 g_byte_array_free(addr
, true);
6754 *err
= g_strdup("Invalid argument. Expected either a CN ID [1-239] or a MAC address");
6759 nodeid_profile_list_uats_nodeid_set_cb(void *_rec
, const char *str
, unsigned len
, const void *set_data _U_
, const void *fld_data _U_
)
6761 struct nodeid_profile_uat_assoc
*rec
= (struct nodeid_profile_uat_assoc
*)_rec
;
6762 GByteArray
*addr
= g_byte_array_new();
6764 rec
->is_nodeid
= true;
6765 if (hex_str_to_bytes(str
, addr
, false) && addr
->len
== FT_ETHER_LEN
) {
6766 alloc_address_wmem(NULL
, &rec
->node
.addr
, AT_ETHER
, FT_ETHER_LEN
, addr
->data
);
6767 rec
->is_nodeid
= false;
6769 else if (!ws_strtou8(str
, NULL
, &rec
->node
.id
))
6771 /* Invalid input. Set this to a bad value and let
6772 * epl_uat_fld_cn_check_cb return an error message. */
6776 g_byte_array_free(addr
, true);
6777 g_free(rec
->id_str
);
6778 rec
->id_str
= g_strndup(str
, len
);
6783 * Editor modelines - https://www.wireshark.org/tools/modelines.html
6788 * indent-tabs-mode: t
6791 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
6792 * :indentSize=8:tabSize=8:noTabs=false: