Fix some "format not a string literal and no format arguments" warnings.
[obnox/wireshark/wip.git] / plugins / ethercat / packet-ethercat-datagram.c
1 /* packet-ethercat-datagram.c
2  * Routines for ethercat packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) 2007 by Beckhoff Automation GmbH
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /* Include files */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <time.h>
37 #include <string.h>
38
39 #include <glib.h>
40
41 #include <epan/packet.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/strutil.h>
44
45 #include "packet-ethercat-datagram.h"
46 #include "packet-ecatmb.h"
47
48 static heur_dissector_list_t heur_subdissector_list;
49 static dissector_handle_t ecat_mailbox_handle;
50
51 /* Define the EtherCAT proto */
52 static int proto_ecat_datagram = -1;
53
54 /* Define the tree for EtherCAT */
55 static int ett_ecat = -1;
56 static int ett_ecat_header = -1;
57 static int ett_ecat_syncman = -1;
58 static int ett_ecat_syncflag = -1;
59 static int ett_ecat_fmmu = -1;
60 static int ett_ecat_fmmu_type = -1;
61 static int ett_ecat_fmmu_active = -1;
62 static int ett_ecat_dc = -1;
63 static int ett_ecat_length = -1;
64 static int ett_ecat_padding = -1;
65 static int ett_ecat_datagram_subtree = -1;
66
67 static int hf_ecat_sub;
68 static int hf_ecat_sub_data[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
69 static int hf_ecat_sub_cmd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
70 static int hf_ecat_sub_idx[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
71 static int hf_ecat_sub_cnt[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
72 static int hf_ecat_sub_ado[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
73 static int hf_ecat_sub_adp[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
74 static int hf_ecat_sub_lad[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
75
76 static int hf_ecat_header = -1;
77 static int hf_ecat_data = -1;
78 static int hf_ecat_cnt = -1;
79 static int hf_ecat_cmd = -1;
80 static int hf_ecat_idx = -1;
81 static int hf_ecat_adp = -1;
82 static int hf_ecat_ado = -1;
83 static int hf_ecat_lad = -1;
84 static int hf_ecat_len = -1;
85 static int hf_ecat_int = -1;
86 static int hf_ecat_syncman = -1;
87 static int hf_ecat_syncman_start = -1;
88 static int hf_ecat_syncman_len = -1;
89 static int hf_ecat_syncman_flags = -1;
90 static int hf_ecat_syncman_flag0 = -1;
91 static int hf_ecat_syncman_flag1 = -1;
92 static int hf_ecat_syncman_flag2 = -1;
93 static int hf_ecat_syncman_flag4 = -1;
94 static int hf_ecat_syncman_flag5 = -1;
95 static int hf_ecat_syncman_flag8 = -1;
96 static int hf_ecat_syncman_flag9 = -1;
97 static int hf_ecat_syncman_flag10 = -1;
98 static int hf_ecat_syncman_flag11 = -1;
99 static int hf_ecat_syncman_flag12 = -1;
100 static int hf_ecat_syncman_flag13 = -1;
101 static int hf_ecat_syncman_flag16 = -1;
102 static int hf_ecat_fmmu = -1;
103 static int hf_ecat_fmmu_lstart = -1;
104 static int hf_ecat_fmmu_llen = -1;
105 static int hf_ecat_fmmu_lstartbit = -1;
106 static int hf_ecat_fmmu_lendbit = -1;
107 static int hf_ecat_fmmu_pstart = -1;
108 static int hf_ecat_fmmu_pstartbit = -1;
109 static int hf_ecat_fmmu_type = -1;
110 static int hf_ecat_fmmu_typeread = -1;
111 static int hf_ecat_fmmu_typewrite = -1;
112 static int hf_ecat_fmmu_active = -1;
113 static int hf_ecat_fmmu_active0 = -1;
114
115 static int hf_ecat_sub_dc_diff_da[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
116 static int hf_ecat_sub_dc_diff_bd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
117 static int hf_ecat_sub_dc_diff_cb[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
118 static int hf_ecat_sub_dc_diff_cd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
119 static int hf_ecat_sub_dc_diff_ba[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
120 static int hf_ecat_sub_dc_diff_ca[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
121
122 static int hf_ecat_dc_diff_da = -1;
123 static int hf_ecat_dc_diff_bd = -1;
124 static int hf_ecat_dc_diff_cb = -1;
125 static int hf_ecat_dc_diff_cd = -1;
126 static int hf_ecat_dc_diff_ba = -1;
127 static int hf_ecat_dc_diff_ca = -1;
128
129 static int hf_ecat_length_len = -1;
130 static int hf_ecat_length_r = -1;
131 static int hf_ecat_length_c = -1;
132 static int hf_ecat_length_m = -1;
133
134 static int hf_ecat_padding = -1;
135
136 static const value_string EcCmdShort[] =
137 {
138    {   0, "NOP" },
139    {   1, "APRD" },
140    {   2, "APWR" },
141    {   3, "APRW" },
142    {   4, "FPRD" },
143    {   5, "FPWR" },
144    {   6, "FPRW" },
145    {   7, "BRD" },
146    {   8, "BWR" },
147    {   9, "BRW" },
148    {   10, "LRD" },
149    {   11, "LWR" },
150    {   12, "LRW" },
151    {   13, "ARMW" },
152    {   14, "FRMW" },
153    {   255, "EXT" },
154    {   0, NULL }
155 };
156
157 static const value_string EcCmdLong[] =
158 {
159    {   0, "No operation" },
160    {   1, "Auto increment read" },
161    {   2, "Auto increment write" },
162    {   3, "Auto increment read write" },
163    {   4, "Configured address read" },
164    {   5, "Configured address write" },
165    {   6, "Configured address read write" },
166    {   7, "Broadcast read" },
167    {   8, "Broadcast write" },
168    {   9, "Broadcast read write" },
169    {   10, "Logical memory read" },
170    {   11, "Logical memory write" },
171    {   12, "Logical memory read write" },
172    {   13, "Auto increment read multiple write" },
173    {   14, "Configured read multiple write" },
174    {   255, "EXT" },
175    {   0, NULL }
176 };
177
178 static const value_string ecat_subframe_reserved_vals[] =
179 {
180    { 0, "Valid"},
181    { 0, NULL}
182 };
183
184 static const value_string ecat_subframe_circulating_vals[] =
185 {
186    { 0, "Frame is not circulating" },
187    { 1, "Frame has circulated once" },
188    { 0, NULL }
189 };
190
191 static const value_string ecat_subframe_more_vals[] =
192 {
193    { 0, "Last EtherCAT datagram"},
194    { 1, "More EtherCAT datagrams will follow"},
195    { 0, NULL}
196 };
197
198 static const true_false_string tfs_ecat_fmmu_typeread =
199 {
200    "Read in use", "Read ignore"
201 };
202
203 static const true_false_string tfs_ecat_fmmu_typewrite =
204 {
205    "Write in use", "Write ignore"
206 };
207
208 static const true_false_string tfs_ecat_fmmu_active =
209 {
210    "Enabled", "Disabled"
211 };
212
213 static const true_false_string tfs_ecat_syncman_flag0 =
214 {
215    "OPMODE xx", "OPMODE xx"
216 };
217
218 static const true_false_string tfs_ecat_syncman_flag1 =
219 {
220    "00: 3-Buf, 01: 3-Buf (Mon.), 10: 1-Buf", "00: 3-Buf, 01: 3-Buf (Mon.), 10: 1-Buf",
221 };
222
223 static const true_false_string tfs_ecat_syncman_flag2 =
224 {
225    "Write", "Read"
226 };
227
228 static const true_false_string tfs_ecat_syncman_flag4 =
229 {
230    "IRQ ECAT enabled", "IRQ ECAT disabled"
231 };
232
233 static const true_false_string tfs_ecat_syncman_flag5 =
234 {
235    "IRQ PDI enabled", "IRQ PDI disabled"
236 };
237
238 static const true_false_string tfs_ecat_syncman_flag8 =
239 {
240    "IRQ Write 1", "IRQ Write 0"
241 };
242
243 static const true_false_string tfs_ecat_syncman_flag9 =
244 {
245    "IRQ Read 1", "IRQ Read 0"
246 };
247
248 static const true_false_string tfs_ecat_syncman_flag10 =
249 {
250    "Watchdog", "No Watchdog"
251 };
252
253 static const true_false_string tfs_ecat_syncman_flag11 =
254 {
255    "1-Buf written", "1-Buf read"
256 };
257
258 static const true_false_string tfs_ecat_syncman_flag12 =
259 {
260    "Buffer Status xx", "Buffer Status xx"
261 };
262
263 static const true_false_string tfs_ecat_syncman_flag13 =
264 {
265    "00: 1.Buf, 01: 2.Buf, 10: 3.Buf", "00: 1.Buf, 01: 2.Buf, 10: 3.Buf"
266 };
267
268 static const true_false_string tfs_ecat_syncman_flag16 =
269 {
270    "SyncMan enabled", "SyncMan disabled",
271 };
272
273 static const char* convertEcCmdToText(int cmd, const value_string ec_cmd[])
274 {
275    return val_to_str(cmd, ec_cmd, "<UNKNOWN: %d>");
276 }
277
278 #define ENDOF(p) ((p)+1) /* pointer to end of *p*/
279
280 typedef enum
281 {
282    EC_CMD_TYPE_NOP  = 0,
283    EC_CMD_TYPE_APRD = 1,
284    EC_CMD_TYPE_APWR = 2,
285    EC_CMD_TYPE_APRW = 3,
286    EC_CMD_TYPE_FPRD = 4,
287    EC_CMD_TYPE_FPWR = 5,
288    EC_CMD_TYPE_FPRW = 6,
289    EC_CMD_TYPE_BRD  = 7,
290    EC_CMD_TYPE_BWR  = 8,
291    EC_CMD_TYPE_BRW  = 9,
292    EC_CMD_TYPE_LRD  = 10,
293    EC_CMD_TYPE_LWR  = 11,
294    EC_CMD_TYPE_LRW  = 12,
295    EC_CMD_TYPE_ARMW = 13,
296    EC_CMD_TYPE_FRMW = 14,
297    EC_CMD_TYPE_EXT  = 255
298 } EC_CMD_TYPE;
299
300 static void init_EcParserHDR(EcParserHDR* pHdr, tvbuff_t *tvb, gint offset)
301 {
302    pHdr->cmd = tvb_get_guint8(tvb, offset++);
303    pHdr->idx = tvb_get_guint8(tvb, offset++);
304    pHdr->anAddrUnion.a.adp = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16);
305    pHdr->anAddrUnion.a.ado = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16);
306    pHdr->len = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16);
307    pHdr->intr = tvb_get_letohs(tvb, offset);
308 }
309
310 static void init_dc_measure(guint32* pDC, tvbuff_t *tvb, gint offset)
311 {
312    int i;
313    for ( i=0; i<4; i++ )
314    {
315       pDC[i] = tvb_get_letohl(tvb, offset);
316       offset+=sizeof(guint32);
317    }
318 }
319
320 static guint16 get_wc(EcParserHDR* pHdr, tvbuff_t *tvb, gint offset)
321 {
322    return tvb_get_letohs(tvb, offset+EcParserHDR_Len+(pHdr->len&0x07ff));
323 }
324
325 static guint16 get_cmd_len(EcParserHDR* pHdr)
326 {
327    return (EcParserHDR_Len+(pHdr->len&0x07ff)+sizeof(guint16)); /*Header + data + wc*/
328 }
329
330
331 static void EcSummaryFormater(guint32 datalength, tvbuff_t *tvb, gint offset, char *szText, gint nMax)
332 {
333    guint nSub=0;
334    guint nLen=0;
335    guint8  nCmds[4];
336    guint nLens[4];
337    EcParserHDR ecFirst;
338    EcParserHDR ecParser;
339
340    guint suboffset=0;
341
342    init_EcParserHDR(&ecFirst, tvb, offset);
343
344    while ( suboffset < datalength )
345    {
346       PEcParserHDR pEcParser;
347       if ( nSub > 0 )
348       {
349          init_EcParserHDR(&ecParser, tvb, offset+suboffset);
350          pEcParser = &ecParser;
351       }
352       else
353          pEcParser = &ecFirst;
354
355       if ( nSub < 4 )
356       {
357          nCmds[nSub] = pEcParser->cmd;
358          nLens[nSub] = pEcParser->len&0x07ff;
359       }
360       nSub++;
361       nLen += (pEcParser->len&0x07ff);
362       /* bit 14 -- roundtrip */
363
364       if ( (pEcParser->len&0x8000) == 0 )
365          break;
366
367       suboffset+=get_cmd_len(pEcParser);
368    }
369    if ( nSub == 1 )
370    {
371       guint16 len = ecFirst.len&0x07ff;
372       guint16 cnt = get_wc(&ecFirst, tvb, offset);
373       g_snprintf ( szText, nMax, "'%s': Len: %d, Adp 0x%x, Ado 0x%x, Wc %d ",
374          convertEcCmdToText(ecFirst.cmd, EcCmdShort), len, ecFirst.anAddrUnion.a.adp, ecFirst.anAddrUnion.a.ado, cnt );
375    }
376    else if ( nSub == 2 )
377    {
378       g_snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d ",
379          nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1]);
380    }
381    else if ( nSub == 3 )
382    {
383       g_snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d, '%s': len %d",
384          nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1], convertEcCmdToText(nCmds[2], EcCmdShort), nLens[2]);
385    }
386    else if ( nSub == 4 )
387    {
388       g_snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d, '%s': len %d, '%s': len %d",
389          nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1], convertEcCmdToText(nCmds[2], EcCmdShort), nLens[2], convertEcCmdToText(nCmds[3], EcCmdShort), nLens[3]);
390    }
391    else
392       g_snprintf ( szText, nMax, "%d Cmds, SumLen %d, '%s'... ",
393          nSub, nLen, convertEcCmdToText(ecFirst.cmd, EcCmdShort));
394 }
395
396 static void EcSubFormatter(tvbuff_t *tvb, gint offset, char *szText, gint nMax)
397 {
398    EcParserHDR ecParser;
399    guint16 len, cnt;
400
401    init_EcParserHDR(&ecParser, tvb, offset);
402    len = ecParser.len&0x07ff;
403    cnt = get_wc(&ecParser, tvb, offset);
404
405    switch ( ecParser.cmd )
406    {
407    case EC_CMD_TYPE_NOP:
408    case EC_CMD_TYPE_APRD:
409    case EC_CMD_TYPE_APWR:
410    case EC_CMD_TYPE_APRW:
411    case EC_CMD_TYPE_FPRD:
412    case EC_CMD_TYPE_FPWR:
413    case EC_CMD_TYPE_FPRW:
414    case EC_CMD_TYPE_BRD:
415    case EC_CMD_TYPE_BWR:
416    case EC_CMD_TYPE_BRW:
417    case EC_CMD_TYPE_ARMW:
418    case EC_CMD_TYPE_FRMW:
419       g_snprintf ( szText, nMax, "EtherCAT datagram: Cmd: '%s' (%d), Len: %d, Adp 0x%x, Ado 0x%x, Cnt %d",
420          convertEcCmdToText(ecParser.cmd, EcCmdShort), ecParser.cmd, len, ecParser.anAddrUnion.a.adp, ecParser.anAddrUnion.a.ado, cnt);
421       break;
422    case EC_CMD_TYPE_LRD:
423    case EC_CMD_TYPE_LWR:
424    case EC_CMD_TYPE_LRW:
425       g_snprintf ( szText, nMax, "EtherCAT datagram: Cmd: '%s' (%d), Len: %d, Addr 0x%x, Cnt %d",
426          convertEcCmdToText(ecParser.cmd, EcCmdShort), ecParser.cmd, len, ecParser.anAddrUnion.addr, cnt);
427       break;
428    case EC_CMD_TYPE_EXT:
429       g_snprintf ( szText, nMax, "EtherCAT datagram: Cmd: 'EXT' (%d), Len: %d",  ecParser.cmd, len);
430       break;
431    default:
432       g_snprintf ( szText, nMax, "EtherCAT datagram: Cmd: 'Unknown' (%d), Len: %d",  ecParser.cmd, len);
433    }
434 }
435
436 /* Ethercat Datagram */
437 static void dissect_ecat_datagram(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
438 {
439    tvbuff_t *next_tvb;
440    proto_item *ti, *aitem = NULL;
441    proto_tree *ecat_datagrams_tree = NULL;
442    guint offset = 0;
443    char szText[200];
444    int nMax = sizeof(szText)-1;
445    guint b;
446
447    guint ecLength=0;
448    guint subCount = 0;
449    const guint datagram_length = tvb_length_remaining(tvb, offset);
450    guint datagram_padding_bytes = 0;
451    EcParserHDR ecHdr;
452
453    if (check_col(pinfo->cinfo, COL_PROTOCOL))
454       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECAT");
455
456    if (check_col(pinfo->cinfo, COL_INFO))
457       col_clear(pinfo->cinfo, COL_INFO);
458
459    /* If the data portion of an EtherCAT datagram is less than 44 bytes, then
460       it must have been padded with an additional n number of bytes to reach a
461       total Ethernet frame length of 64 bytes (Ethernet header + Ethernet Data +
462       FCS). Hence at least 44 bytes data shall always be available in any
463       EtherCAT datagram. */
464    /* tvb_ensure_bytes_exist(tvb, offset, 44);
465       this is not correct, because the frame might have been captured before the
466       os added the padding bytes. E.g. in Windows the frames are captured on the
467       protocol layer. When another protocol driver sends a frame this frame does
468       not include the padding bytes.    
469    */
470
471    /* Count the length of the individual EtherCAT datagrams (sub datagrams)
472       that are part of this EtherCAT frame. Stop counting when the current
473       sub datagram header tells that there are no more sub datagrams or when
474       there is no more data available in the PDU. */
475    do
476    {
477       init_EcParserHDR(&ecHdr, tvb, ecLength);
478       ecLength += get_cmd_len(&ecHdr);
479    } while ((ecLength < datagram_length) &&
480             (ecHdr.len & 0x8000));
481
482    /* Calculate the amount of padding data available in the PDU */
483    datagram_padding_bytes = datagram_length - ecLength;
484
485    EcSummaryFormater(ecLength, tvb, offset, szText, nMax);
486    if (check_col(pinfo->cinfo, COL_INFO))
487       col_append_str(pinfo->cinfo, COL_INFO, szText);
488
489    if( tree )
490    {
491       /* Create the EtherCAT datagram(s) subtree */
492       ti = proto_tree_add_item(tree, proto_ecat_datagram, tvb, 0, -1, TRUE);
493       ecat_datagrams_tree = proto_item_add_subtree(ti, ett_ecat);
494
495       proto_item_append_text(ti,": %s", szText);
496    }
497
498    /* Dissect all sub frames of this EtherCAT PDU */
499    do
500    {
501       proto_tree *ecat_datagram_tree = NULL, *ecat_header_tree = NULL, *ecat_fmmu_tree = NULL,
502                  *ecat_fmmu_active_tree = NULL, *ecat_fmmu_type_tree = NULL, *ecat_syncman_tree = NULL,
503                  *ecat_syncflag_tree = NULL, *ecat_dc_tree = NULL;
504           proto_item *hidden_item;
505
506       gint bMBox = FALSE;
507       guint32 subsize;
508       guint32 suboffset;
509       guint32 len;
510       ETHERCAT_MBOX_HEADER mbox;
511
512       suboffset = offset;
513       init_EcParserHDR(&ecHdr, tvb, suboffset);
514
515       subsize = get_cmd_len(&ecHdr);
516       len = ecHdr.len & 0x07ff;
517
518       if ( len >= sizeof(ETHERCAT_MBOX_HEADER_LEN) &&
519            (ecHdr.cmd==EC_CMD_TYPE_FPWR || ecHdr.cmd==EC_CMD_TYPE_FPRD || ecHdr.cmd==EC_CMD_TYPE_APWR || ecHdr.cmd==EC_CMD_TYPE_APRD) &&
520            ecHdr.anAddrUnion.a.ado>=0x1000
521          )
522       {
523          init_mbx_header(&mbox, tvb, suboffset+EcParserHDR_Len);
524
525          switch ( mbox.aControlUnion.v.Type )
526          {
527          case ETHERCAT_MBOX_TYPE_EOE:
528          case ETHERCAT_MBOX_TYPE_ADS:
529          case ETHERCAT_MBOX_TYPE_FOE:
530          case ETHERCAT_MBOX_TYPE_COE:
531          case ETHERCAT_MBOX_TYPE_SOE:
532             if ( /*pMBox->Length > 0 &&*/ mbox.Length <= 1500 /*&& pMBox->Length+sizeof(ETHERCAT_MBOX_HEADER_LEN) >= len*/ )
533             {
534                bMBox = TRUE;
535             }
536             break;
537          }
538       }
539
540       if( tree )
541       {
542          /* Create the sub tree for the current datagram */
543          EcSubFormatter(tvb, suboffset, szText, nMax);
544          aitem = proto_tree_add_text(ecat_datagrams_tree, tvb, suboffset, subsize, "%s", szText);
545          ecat_datagram_tree = proto_item_add_subtree(aitem, ett_ecat_datagram_subtree);
546
547          /* Create a subtree placeholder for the Header */
548          aitem = proto_tree_add_text(ecat_datagram_tree, tvb, offset, EcParserHDR_Len, "Header");
549          ecat_header_tree = proto_item_add_subtree(aitem, ett_ecat_header);
550
551          aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_cmd, tvb, suboffset, sizeof(ecHdr.cmd), TRUE);
552          if( subCount < 10 ){
553             aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_cmd[subCount], tvb, suboffset, sizeof(ecHdr.cmd), TRUE);
554                         PROTO_ITEM_SET_HIDDEN(aitem);
555                  }
556
557          suboffset+= sizeof(ecHdr.cmd);
558
559          aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_idx, tvb, suboffset, sizeof(ecHdr.idx), TRUE);
560          if( subCount < 10 ){
561             aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_idx[subCount], tvb, suboffset, sizeof(ecHdr.idx), TRUE);
562                         PROTO_ITEM_SET_HIDDEN(aitem);
563                  }
564          suboffset+= sizeof(ecHdr.idx);
565
566          switch ( ecHdr.cmd )
567          {
568          case 10:
569          case 11:
570          case 12:
571             aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_lad, tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.adp)+sizeof(ecHdr.anAddrUnion.a.ado), TRUE);
572             if( subCount < 10 ){
573                aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_lad[subCount], tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.adp)+sizeof(ecHdr.anAddrUnion.a.ado), TRUE);
574                            PROTO_ITEM_SET_HIDDEN(aitem);
575                         }
576
577             suboffset += (sizeof(ecHdr.anAddrUnion.a.adp)+sizeof(ecHdr.anAddrUnion.a.ado));
578             break;
579          default:
580             aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_adp, tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.adp), TRUE);
581             if( subCount < 10 ){
582                aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_adp[subCount], tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.adp), TRUE);
583                            PROTO_ITEM_SET_HIDDEN(aitem);
584                         }
585
586             suboffset+= sizeof(ecHdr.anAddrUnion.a.adp);
587             aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_ado, tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.ado), TRUE);
588             if( subCount < 10 ){
589                aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_ado[subCount], tvb, suboffset, sizeof(ecHdr.anAddrUnion.a.ado), TRUE);
590                            PROTO_ITEM_SET_HIDDEN(aitem);
591                         }
592
593             suboffset+= sizeof(ecHdr.anAddrUnion.a.ado);
594          }
595
596          {
597             proto_tree *length_sub_tree;
598
599             /* Add information about the length field (11 bit length, 3 bits
600                reserved, 1 bit circulating frame and 1 bit more in a sub tree */
601             aitem = proto_tree_add_text(ecat_header_tree, tvb, suboffset, sizeof(ecHdr.len),
602                                         "Length     : %d (0x%x) - %s - %s",
603                                         len, len, ecHdr.len & 0x4000 ? "Roundtrip" : "No Roundtrip", ecHdr.len & 0x8000 ? "More Follows..." : "Last Sub Command");
604             length_sub_tree = proto_item_add_subtree(aitem, ett_ecat_length);
605
606             proto_tree_add_item(length_sub_tree, hf_ecat_length_len, tvb, suboffset, sizeof(ecHdr.len), TRUE);
607             proto_tree_add_item(length_sub_tree, hf_ecat_length_r, tvb, suboffset, sizeof(ecHdr.len), TRUE);
608             proto_tree_add_item(length_sub_tree, hf_ecat_length_c, tvb, suboffset, sizeof(ecHdr.len), TRUE);
609             proto_tree_add_item(length_sub_tree, hf_ecat_length_m, tvb, suboffset, sizeof(ecHdr.len), TRUE);
610
611             suboffset+= sizeof(ecHdr.len);
612          }
613
614          aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_int, tvb, suboffset, sizeof(ecHdr.intr), TRUE);
615          suboffset+= sizeof(ecHdr.intr);
616       }
617       else
618       {
619          suboffset+=EcParserHDR_Len;
620       }
621
622       if ( ecHdr.cmd>=1 && ecHdr.cmd<=9 && ecHdr.anAddrUnion.a.ado>=0x600 && ecHdr.anAddrUnion.a.ado<0x700 && (ecHdr.anAddrUnion.a.ado%16)==0 && (len%16)==0 )
623       {
624          if( tree )
625          {
626             /* Fieldbus Memory Management Units (FMMU) */
627             for ( b=0; b < MIN(16, len/16); b++ )
628             {
629                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_fmmu, tvb, suboffset, 16, TRUE);
630                proto_item_set_text(aitem, "Fieldbus Memory Management Units (FMMU)");
631
632                ecat_fmmu_tree = proto_item_add_subtree(aitem, ett_ecat_fmmu);
633
634                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_lstart, tvb, suboffset, 4, TRUE);
635                suboffset += 4;
636                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_llen, tvb, suboffset, 2, TRUE);
637                suboffset += 2;
638                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_lstartbit, tvb, suboffset, 1, TRUE);
639                suboffset += 1;
640                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_lendbit, tvb, suboffset, 1, TRUE);
641                suboffset += 1;
642                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_pstart, tvb, suboffset, 2, TRUE);
643                suboffset += 2;
644                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_pstartbit, tvb, suboffset, 1, TRUE);
645                suboffset += 1;
646                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_type, tvb, suboffset, 1, TRUE);
647                ecat_fmmu_type_tree = proto_item_add_subtree(aitem, ett_ecat_fmmu_type);
648                aitem = proto_tree_add_item(ecat_fmmu_type_tree, hf_ecat_fmmu_typeread, tvb, suboffset, 1, TRUE);
649                aitem = proto_tree_add_item(ecat_fmmu_type_tree, hf_ecat_fmmu_typewrite, tvb, suboffset, 1, TRUE);
650
651                suboffset += 1;
652                aitem = proto_tree_add_item(ecat_fmmu_tree, hf_ecat_fmmu_active, tvb, suboffset, 1, TRUE);
653                ecat_fmmu_active_tree = proto_item_add_subtree(aitem, ett_ecat_fmmu_active);
654                aitem = proto_tree_add_item(ecat_fmmu_active_tree, hf_ecat_fmmu_active0, tvb, suboffset, 1, TRUE);
655
656                suboffset += 4;
657             }
658             if ( len > 0x100 )
659             {
660                len -= 0x100;
661                for (b = 0; b < MIN(32, len / 8); b++)
662                {
663                   aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_syncman, tvb, suboffset, 8, TRUE);
664                   proto_item_set_text(aitem, "SyncManager");
665                   ecat_syncman_tree = proto_item_add_subtree(aitem, ett_ecat_syncman);
666
667                   aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_start, tvb, suboffset, 2, TRUE);
668                   suboffset+=2;
669                   aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_len, tvb, suboffset, 2, TRUE);
670                   suboffset+=2;
671
672                   aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_flags, tvb, suboffset, 4, TRUE);
673                   ecat_syncflag_tree = proto_item_add_subtree(aitem, ett_ecat_syncflag);
674                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag0, tvb, suboffset, 4, TRUE);
675                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag1, tvb, suboffset, 4, TRUE);
676                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag2, tvb, suboffset, 4, TRUE);
677                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag4, tvb, suboffset, 4, TRUE);
678                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag5, tvb, suboffset, 4, TRUE);
679                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag8, tvb, suboffset, 4, TRUE);
680                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag9, tvb, suboffset, 4, TRUE);
681                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag10, tvb, suboffset, 4, TRUE);
682                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag11, tvb, suboffset, 4, TRUE);
683                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag12, tvb, suboffset, 4, TRUE);
684                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag13, tvb, suboffset, 4, TRUE);
685                   aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag16, tvb, suboffset, 4, TRUE);
686                   suboffset+=4;
687                }
688             }
689          }
690       }
691       else if ( ecHdr.cmd>=1 && ecHdr.cmd<=9 && ecHdr.anAddrUnion.a.ado>=0x800 && ecHdr.anAddrUnion.a.ado<0x880 && (ecHdr.anAddrUnion.a.ado%8)==0 && (len%8)==0 )
692       {
693          if( tree )
694          {
695             /* SyncManager */
696             for (b = 0; b < MIN(32, len / 8); b++)
697             {
698                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_syncman, tvb, suboffset, 8, TRUE);
699                proto_item_set_text(aitem, "SyncManager");
700                ecat_syncman_tree = proto_item_add_subtree(aitem, ett_ecat_syncman);
701
702                aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_start, tvb, suboffset, 2, TRUE);
703                suboffset+=2;
704                aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_len, tvb, suboffset, 2, TRUE);
705                suboffset+=2;
706
707                aitem = proto_tree_add_item(ecat_syncman_tree, hf_ecat_syncman_flags, tvb, suboffset, 4, TRUE);
708                ecat_syncflag_tree = proto_item_add_subtree(aitem, ett_ecat_syncflag);
709                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag0, tvb, suboffset, 4, TRUE);
710                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag1, tvb, suboffset, 4, TRUE);
711                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag2, tvb, suboffset, 4, TRUE);
712                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag4, tvb, suboffset, 4, TRUE);
713                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag5, tvb, suboffset, 4, TRUE);
714                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag8, tvb, suboffset, 4, TRUE);
715                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag9, tvb, suboffset, 4, TRUE);
716                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag10, tvb, suboffset, 4, TRUE);
717                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag11, tvb, suboffset, 4, TRUE);
718                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag12, tvb, suboffset, 4, TRUE);
719                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag13, tvb, suboffset, 4, TRUE);
720                aitem = proto_tree_add_item(ecat_syncflag_tree, hf_ecat_syncman_flag16, tvb, suboffset, 4, TRUE);
721                suboffset+=4;
722             }
723          }
724       }
725       else if ( (ecHdr.cmd == 1 || ecHdr.cmd == 4) && ecHdr.anAddrUnion.a.ado == 0x900 && ecHdr.len >= 16 )
726       {
727          if (tree)
728          {
729             guint32 pDC[4];
730             init_dc_measure(pDC, tvb, suboffset);
731
732             /* Allow sub dissectors to have a chance with this data */
733             if(!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, ecat_datagram_tree))
734             {
735                /* No sub dissector did recognize this data, dissect it as data only */
736                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_data, tvb, suboffset, ecHdr.len & 0x07ff, TRUE);
737                ecat_dc_tree = proto_item_add_subtree(aitem, ett_ecat_dc);
738             }
739             else
740             {
741                /* A sub dissector handled the data, allow the rest of the
742                   to add data to the correct place in the tree hierarchy. */
743                ecat_dc_tree = ecat_datagram_tree;
744             }
745
746             if( subCount < 10 ){
747                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_data[subCount], tvb, offset + EcParserHDR_Len, ecHdr.len & 0x07ff, TRUE);
748                            PROTO_ITEM_SET_HIDDEN(aitem);
749                         }
750
751             if ( pDC[3] != 0 )
752             {
753                proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_da, tvb, suboffset, 4, pDC[3] - pDC[0]);
754                if( subCount < 10 ){
755                   hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_da[subCount], tvb, suboffset, 4, pDC[3] - pDC[0]);
756                                   PROTO_ITEM_SET_HIDDEN(aitem);
757                            }
758
759                if ( pDC[1] != 0 )
760                {
761                   proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_bd, tvb, suboffset, 4, pDC[1] - pDC[3]);
762                   if( subCount < 10 ){
763                                           hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_bd[subCount], tvb, suboffset, 4, pDC[1] - pDC[3]);
764                                           PROTO_ITEM_SET_HIDDEN(aitem);
765                                   }
766                }
767                else if ( pDC[2] != 0 )
768                {
769                   proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_cd, tvb, suboffset, 4, pDC[2] - pDC[3]);
770                   if( subCount < 10 ){
771                      hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_cd[subCount], tvb, suboffset, 4, pDC[2] - pDC[3]);
772                                          PROTO_ITEM_SET_HIDDEN(aitem);
773                                   }
774                }
775             }
776             if ( pDC[1] != 0 )
777             {
778                proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_ba, tvb, suboffset, 4, pDC[1] - pDC[0]);
779                if( subCount < 10 ){
780                   hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_ba[subCount], tvb, suboffset, 4, pDC[1] - pDC[0]);
781                                   PROTO_ITEM_SET_HIDDEN(aitem);
782                            }
783                if ( pDC[2] != 0 )
784                {
785                   proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_cb, tvb, suboffset, 4, pDC[2] - pDC[1]);
786                   if( subCount < 10 ){
787                      hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_cb[subCount], tvb, suboffset, 4, pDC[2] - pDC[1]);
788                                          PROTO_ITEM_SET_HIDDEN(aitem);
789                                   }
790                }
791             }
792             else if ( pDC[2] != 0 )
793             {
794                proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_ca, tvb, suboffset, 4, pDC[2] - pDC[0]);
795                if( subCount < 10 ){
796                   hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_ca[subCount], tvb, suboffset, 4, pDC[2] - pDC[0]);
797                                   PROTO_ITEM_SET_HIDDEN(aitem);
798                            }
799             }
800          }
801       }
802       else if ( bMBox )
803       {
804          const guint MBoxLength = mbox.Length + 6 /* MBOX header length */;
805
806          next_tvb = tvb_new_subset(tvb, suboffset, MBoxLength, MBoxLength);
807          call_dissector(ecat_mailbox_handle, next_tvb, pinfo, ecat_datagram_tree);
808
809          if( tree )
810          {
811             const guint startOfData = offset + EcParserHDR_Len + MBoxLength;
812             const guint dataLength = (ecHdr.len & 0x7ff) - MBoxLength;
813             if ( dataLength > 0 )
814             {
815                /* Allow sub dissectors to have a chance with this data */
816                if(!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, ecat_datagram_tree))
817                {
818                   /* No sub dissector did recognize this data, dissect it as data only */
819                   aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_data, tvb, startOfData, dataLength, TRUE);
820                }
821
822                if( subCount < 10 ){
823                   aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_data[subCount], tvb, startOfData, dataLength, TRUE);
824                               PROTO_ITEM_SET_HIDDEN(aitem);
825                    }
826             }
827          }
828       }
829       else
830       {
831          if( tree )
832          {
833             /* Allow sub dissectors to have a chance with this data */
834             if(!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, ecat_datagram_tree))
835             {
836                /* No sub dissector did recognize this data, dissect it as data only */
837                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_data, tvb, suboffset, ecHdr.len & 0x07ff, TRUE);
838             }
839
840             if( subCount < 10 ){
841                aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_data[subCount], tvb, offset + EcParserHDR_Len, ecHdr.len & 0x07ff, TRUE);
842                            PROTO_ITEM_SET_HIDDEN(aitem);
843                         }
844          }
845       }
846
847       if( tree )
848       {
849          aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_cnt, tvb, offset + EcParserHDR_Len + len , 2, TRUE);
850          if( subCount < 10 ){
851             aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_cnt[subCount], tvb, offset + EcParserHDR_Len + len , 2, TRUE);
852                         PROTO_ITEM_SET_HIDDEN(aitem);
853                  }
854       }
855
856       offset+=subsize;
857       subCount++;
858    } while((offset < datagram_length) &&
859            (ecHdr.len & 0x8000));
860
861    /* Add information that states which portion of the PDU that is pad bytes.
862       These are added just to get an Ethernet frame size of at least 64 bytes,
863       which is required by the protocol specification */
864    if(datagram_padding_bytes > 0)
865    {
866       proto_tree_add_item(tree, hf_ecat_padding, tvb, offset, tvb_length_remaining(tvb, offset), TRUE);
867    }
868 }
869
870 void proto_register_ecat(void)
871 {
872    static hf_register_info hf[] =
873    {
874       { &hf_ecat_sub,
875       { "EtherCAT Frame", "ecat.sub", FT_BYTES, BASE_NONE, NULL, 0x0,
876       "", HFILL }
877       },
878       { &hf_ecat_header,
879       { "Header", "ecat.header",
880       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
881       },
882       { &hf_ecat_sub_data[0],
883       {  "Data      ", "ecat.sub1.data",
884       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
885       },
886       { &hf_ecat_sub_data[1],
887       {  "Data      ", "ecat.sub2.data",
888       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
889       },
890       { &hf_ecat_sub_data[2],
891       {  "Data      ", "ecat.sub3.data",
892       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
893       },
894       { &hf_ecat_sub_data[3],
895       {  "Data      ", "ecat.sub4.data",
896       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
897       },
898       { &hf_ecat_sub_data[4],
899       {  "Data      ", "ecat.sub5.data",
900       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
901       },
902       { &hf_ecat_sub_data[5],
903       {  "Data      ", "ecat.sub6.data",
904       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
905       },
906       { &hf_ecat_sub_data[6],
907       {  "Data      ", "ecat.sub7.data",
908       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
909       },
910       { &hf_ecat_sub_data[7],
911       {  "Data      ", "ecat.sub8.data",
912       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
913       },
914       { &hf_ecat_sub_data[8],
915       {  "Data      ", "ecat.sub9.data",
916       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
917       },
918       { &hf_ecat_sub_data[9],
919       {  "Data      ", "ecat.sub10.data",
920       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
921       },
922       { &hf_ecat_data,
923       {  "Data      ", "ecat.data",
924       FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
925       },
926       { &hf_ecat_cnt,
927       { "Working Cnt", "ecat.cnt",
928       FT_UINT16, BASE_DEC, NULL, 0x0, "The working counter is increased once for each addressed device if at least one byte/bit of the data was successfully read and/or written by that device, it is increased once for every operation made by that device - read/write/read and write", HFILL }
929       },
930       { &hf_ecat_sub_cnt[0],
931       { "Working Cnt", "ecat.sub1.cnt",
932       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
933       },
934       { &hf_ecat_sub_cnt[1],
935       { "Working Cnt", "ecat.sub2.cnt",
936       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
937       },
938       { &hf_ecat_sub_cnt[2],
939       { "Working Cnt", "ecat.sub3.cnt",
940       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
941       },
942       { &hf_ecat_sub_cnt[3],
943       { "Working Cnt", "ecat.sub4.cnt",
944       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
945       },
946       { &hf_ecat_sub_cnt[4],
947       { "Working Cnt", "ecat.sub5.cnt",
948       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
949       },
950       { &hf_ecat_sub_cnt[5],
951       { "Working Cnt", "ecat.sub6.cnt",
952       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
953       },
954       { &hf_ecat_sub_cnt[6],
955       { "Working Cnt", "ecat.sub7.cnt",
956       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
957       },
958       { &hf_ecat_sub_cnt[7],
959       { "Working Cnt", "ecat.sub8.cnt",
960       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
961       },
962       { &hf_ecat_sub_cnt[8],
963       { "Working Cnt", "ecat.sub9.cnt",
964       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
965       },
966       { &hf_ecat_sub_cnt[9],
967       { "Working Cnt", "ecat.sub10.cnt",
968       FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
969       },
970       { &hf_ecat_cmd,
971       { "Command    ", "ecat.cmd",
972       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
973       },
974       { &hf_ecat_sub_cmd[0],
975       { "Command    ", "ecat.sub1.cmd",
976       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
977       },
978       { &hf_ecat_sub_cmd[1],
979       { "Command    ", "ecat.sub2.cmd",
980       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
981       },
982       { &hf_ecat_sub_cmd[2],
983       { "Command    ", "ecat.sub3.cmd",
984       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
985       },
986       { &hf_ecat_sub_cmd[3],
987       { "Command    ", "ecat.sub4.cmd",
988       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
989       },
990       { &hf_ecat_sub_cmd[4],
991       { "Command    ", "ecat.sub5.cmd",
992       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
993       },
994       { &hf_ecat_sub_cmd[5],
995       { "Command    ", "ecat.sub6.cmd",
996       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
997       },
998       { &hf_ecat_sub_cmd[6],
999       { "Command    ", "ecat.sub7.cmd",
1000       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
1001       },
1002       { &hf_ecat_sub_cmd[7],
1003       { "Command    ", "ecat.sub8.cmd",
1004       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
1005       },
1006       { &hf_ecat_sub_cmd[8],
1007       { "Command    ", "ecat.sub9.cmd",
1008       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
1009       },
1010       { &hf_ecat_sub_cmd[9],
1011       { "Command    ", "ecat.sub10.cmd",
1012       FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, "", HFILL }
1013       },
1014       { &hf_ecat_idx,
1015       { "Index      ", "ecat.idx",
1016       FT_UINT8, BASE_HEX, NULL, 0x0,
1017       "", HFILL }
1018       },
1019       { &hf_ecat_sub_idx[0],
1020       { "Index      ", "ecat.sub1.idx",
1021       FT_UINT8, BASE_HEX, NULL, 0x0,
1022       "", HFILL }
1023       },
1024       { &hf_ecat_sub_idx[1],
1025       { "Index      ", "ecat.sub2.idx",
1026       FT_UINT8, BASE_HEX, NULL, 0x0,
1027       "", HFILL }
1028       },
1029       { &hf_ecat_sub_idx[2],
1030       { "Index      ", "ecat.sub3.idx",
1031       FT_UINT8, BASE_HEX, NULL, 0x0,
1032       "", HFILL }
1033       },
1034       { &hf_ecat_sub_idx[3],
1035       { "Index      ", "ecat.sub4.idx",
1036       FT_UINT8, BASE_HEX, NULL, 0x0,
1037       "", HFILL }
1038       },
1039       { &hf_ecat_sub_idx[4],
1040       { "Index      ", "ecat.sub5.idx",
1041       FT_UINT8, BASE_HEX, NULL, 0x0,
1042       "", HFILL }
1043       },
1044       { &hf_ecat_sub_idx[5],
1045       { "Index      ", "ecat.sub6.idx",
1046       FT_UINT8, BASE_HEX, NULL, 0x0,
1047       "", HFILL }
1048       },
1049       { &hf_ecat_sub_idx[6],
1050       { "Index      ", "ecat.sub7.idx",
1051       FT_UINT8, BASE_HEX, NULL, 0x0,
1052       "", HFILL }
1053       },
1054       { &hf_ecat_sub_idx[7],
1055       { "Index      ", "ecat.sub8.idx",
1056       FT_UINT8, BASE_HEX, NULL, 0x0,
1057       "", HFILL }
1058       },
1059       { &hf_ecat_sub_idx[8],
1060       { "Index      ", "ecat.sub9.idx",
1061       FT_UINT8, BASE_HEX, NULL, 0x0,
1062       "", HFILL }
1063       },
1064       { &hf_ecat_sub_idx[9],
1065       { "Index      ", "ecat.sub10.idx",
1066       FT_UINT8, BASE_HEX, NULL, 0x0,
1067       "", HFILL }
1068       },
1069       { &hf_ecat_adp,
1070       { "Slave Addr ", "ecat.adp",
1071       FT_UINT16, BASE_HEX, NULL, 0x0,
1072       "", HFILL }
1073       },
1074       { &hf_ecat_sub_adp[0],
1075       { "Slave Addr ", "ecat.sub1.adp",
1076       FT_UINT16, BASE_HEX, NULL, 0x0,
1077       "", HFILL }
1078       },
1079       { &hf_ecat_sub_adp[1],
1080       { "Slave Addr ", "ecat.sub2.adp",
1081       FT_UINT16, BASE_HEX, NULL, 0x0,
1082       "", HFILL }
1083       },
1084       { &hf_ecat_sub_adp[2],
1085       { "Slave Addr ", "ecat.sub3.adp",
1086       FT_UINT16, BASE_HEX, NULL, 0x0,
1087       "", HFILL }
1088       },
1089       { &hf_ecat_sub_adp[3],
1090       { "Slave Addr ", "ecat.sub4.adp",
1091       FT_UINT16, BASE_HEX, NULL, 0x0,
1092       "", HFILL }
1093       },
1094       { &hf_ecat_sub_adp[4],
1095       { "Slave Addr ", "ecat.sub5.adp",
1096       FT_UINT16, BASE_HEX, NULL, 0x0,
1097       "", HFILL }
1098       },
1099       { &hf_ecat_sub_adp[5],
1100       { "Slave Addr ", "ecat.sub6.adp",
1101       FT_UINT16, BASE_HEX, NULL, 0x0,
1102       "", HFILL }
1103       },
1104       { &hf_ecat_sub_adp[6],
1105       { "Slave Addr ", "ecat.sub7.adp",
1106       FT_UINT16, BASE_HEX, NULL, 0x0,
1107       "", HFILL }
1108       },
1109       { &hf_ecat_sub_adp[7],
1110       { "Slave Addr ", "ecat.sub8.adp",
1111       FT_UINT16, BASE_HEX, NULL, 0x0,
1112       "", HFILL }
1113       },
1114       { &hf_ecat_sub_adp[8],
1115       { "Slave Addr ", "ecat.sub9.adp",
1116       FT_UINT16, BASE_HEX, NULL, 0x0,
1117       "", HFILL }
1118       },
1119       { &hf_ecat_sub_adp[9],
1120       { "Slave Addr ", "ecat.sub10.adp",
1121       FT_UINT16, BASE_HEX, NULL, 0x0,
1122       "", HFILL }
1123       },
1124       { &hf_ecat_ado,
1125       { "Offset Addr", "ecat.ado",
1126       FT_UINT16, BASE_HEX, NULL, 0x0,
1127       "", HFILL }
1128       },
1129       { &hf_ecat_sub_ado[0],
1130       { "Offset Addr", "ecat.sub1.ado",
1131       FT_UINT16, BASE_HEX, NULL, 0x0,
1132       "", HFILL }
1133       },
1134       { &hf_ecat_sub_ado[1],
1135       { "Offset Addr", "ecat.sub2.ado",
1136       FT_UINT16, BASE_HEX, NULL, 0x0,
1137       "", HFILL }
1138       },
1139       { &hf_ecat_sub_ado[2],
1140       { "Offset Addr", "ecat.sub3.ado",
1141       FT_UINT16, BASE_HEX, NULL, 0x0,
1142       "", HFILL }
1143       },
1144       { &hf_ecat_sub_ado[3],
1145       { "Offset Addr", "ecat.sub4.ado",
1146       FT_UINT16, BASE_HEX, NULL, 0x0,
1147       "", HFILL }
1148       },
1149       { &hf_ecat_sub_ado[4],
1150       { "Offset Addr", "ecat.sub5.ado",
1151       FT_UINT16, BASE_HEX, NULL, 0x0,
1152       "", HFILL }
1153       },
1154       { &hf_ecat_sub_ado[5],
1155       { "Offset Addr", "ecat.sub6.ado",
1156       FT_UINT16, BASE_HEX, NULL, 0x0,
1157       "", HFILL }
1158       },
1159       { &hf_ecat_sub_ado[6],
1160       { "Offset Addr", "ecat.sub7.ado",
1161       FT_UINT16, BASE_HEX, NULL, 0x0,
1162       "", HFILL }
1163       },
1164       { &hf_ecat_sub_ado[7],
1165       { "Offset Addr", "ecat.sub8.ado",
1166       FT_UINT16, BASE_HEX, NULL, 0x0,
1167       "", HFILL }
1168       },
1169       { &hf_ecat_sub_ado[8],
1170       { "Offset Addr", "ecat.sub9.ado",
1171       FT_UINT16, BASE_HEX, NULL, 0x0,
1172       "", HFILL }
1173       },
1174       { &hf_ecat_sub_ado[9],
1175       { "Offset Addr", "ecat.sub10.ado",
1176       FT_UINT16, BASE_HEX, NULL, 0x0,
1177       "", HFILL }
1178       },
1179       { &hf_ecat_lad,
1180       { "Log Addr   ", "ecat.lad",
1181       FT_UINT32, BASE_HEX, NULL, 0x0,
1182       "", HFILL }
1183       },
1184       { &hf_ecat_sub_lad[0],
1185       { "Log Addr   ", "ecat.sub1.lad",
1186       FT_UINT32, BASE_HEX, NULL, 0x0,
1187       "", HFILL }
1188       },
1189       { &hf_ecat_sub_lad[1],
1190       { "Log Addr   ", "ecat.sub2.lad",
1191       FT_UINT32, BASE_HEX, NULL, 0x0,
1192       "", HFILL }
1193       },
1194       { &hf_ecat_sub_lad[2],
1195       { "Log Addr   ", "ecat.sub3.lad",
1196       FT_UINT32, BASE_HEX, NULL, 0x0,
1197       "", HFILL }
1198       },
1199       { &hf_ecat_sub_lad[3],
1200       { "Log Addr   ", "ecat.sub4.lad",
1201       FT_UINT32, BASE_HEX, NULL, 0x0,
1202       "", HFILL }
1203       },
1204       { &hf_ecat_sub_lad[4],
1205       { "Log Addr   ", "ecat.sub5.lad",
1206       FT_UINT32, BASE_HEX, NULL, 0x0,
1207       "", HFILL }
1208       },
1209       { &hf_ecat_sub_lad[5],
1210       { "Log Addr   ", "ecat.sub6.lad",
1211       FT_UINT32, BASE_HEX, NULL, 0x0,
1212       "", HFILL }
1213       },
1214       { &hf_ecat_sub_lad[6],
1215       { "Log Addr   ", "ecat.sub7.lad",
1216       FT_UINT32, BASE_HEX, NULL, 0x0,
1217       "", HFILL }
1218       },
1219       { &hf_ecat_sub_lad[7],
1220       { "Log Addr   ", "ecat.sub8.lad",
1221       FT_UINT32, BASE_HEX, NULL, 0x0,
1222       "", HFILL }
1223       },
1224       { &hf_ecat_sub_lad[8],
1225       { "Log Addr   ", "ecat.sub9.lad",
1226       FT_UINT32, BASE_HEX, NULL, 0x0,
1227       "", HFILL }
1228       },
1229       { &hf_ecat_sub_lad[9],
1230       { "Log Addr   ", "ecat.sub10.lad",
1231       FT_UINT32, BASE_HEX, NULL, 0x0,
1232       "", HFILL }
1233       },
1234       { &hf_ecat_len,
1235       { "Length     ", "ecat.len",
1236       FT_UINT16, BASE_DEC, NULL, 0x0,
1237       "", HFILL }
1238       },
1239       { &hf_ecat_int,
1240       { "Interrupt  ", "ecat.int",
1241       FT_UINT16, BASE_HEX, NULL, 0x0,
1242       "", HFILL }
1243       },
1244       { &hf_ecat_syncman,
1245       { "SyncManager", "ecat.syncman",
1246       FT_BYTES, BASE_NONE, NULL, 0x0,
1247       "", HFILL }
1248       },
1249       { &hf_ecat_syncman_start,
1250       { "Start Addr", "ecat.syncman.start",
1251       FT_UINT16, BASE_HEX, NULL, 0x0,
1252       "", HFILL }
1253       },
1254       { &hf_ecat_syncman_len,
1255       { "SM Length ", "ecat.syncman.len",
1256       FT_UINT16, BASE_HEX, NULL, 0x0,
1257       "", HFILL }
1258       },
1259       { &hf_ecat_syncman_flags,
1260       { "SM Flags ", "ecat.syncman.flags",
1261       FT_UINT32, BASE_HEX, NULL, 0x0,
1262       "", HFILL }
1263       },
1264       { &hf_ecat_syncman_flag0,
1265       { "SM Flag0", "ecat.syncman_flag0",
1266       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag0), 0x00000001,
1267       "", HFILL }
1268       },
1269       { &hf_ecat_syncman_flag1,
1270       { "SM Flag1", "ecat.syncman_flag1",
1271       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag1), 0x00000002,
1272       "", HFILL }
1273       },
1274       { &hf_ecat_syncman_flag2,
1275       { "SM Flag2", "ecat.syncman_flag2",
1276       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag2), 0x00000004,
1277       "", HFILL }
1278       },
1279       { &hf_ecat_syncman_flag4,
1280       { "SM Flag4", "ecat.syncman_flag4",
1281       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag4), 0x00000010,
1282       "", HFILL }
1283       },
1284       { &hf_ecat_syncman_flag5,
1285       { "SM Flag5", "ecat.syncman_flag5",
1286       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag5), 0x00000020,
1287       "", HFILL }
1288       },
1289       { &hf_ecat_syncman_flag8,
1290       { "SM Flag8", "ecat.syncman_flag8",
1291       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag8), 0x00000100,
1292       "", HFILL }
1293       },
1294       { &hf_ecat_syncman_flag9,
1295       { "SM Flag9", "ecat.syncman_flag9",
1296       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag9), 0x00000200,
1297       "", HFILL }
1298       },
1299       { &hf_ecat_syncman_flag10,
1300       { "SM Flag10", "ecat.syncman_flag10",
1301       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag10), 0x00000400,
1302       "", HFILL }
1303       },
1304       { &hf_ecat_syncman_flag11,
1305       { "SM Flag11", "ecat.syncman_flag11",
1306       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag11), 0x00000800,
1307       "", HFILL }
1308       },
1309       { &hf_ecat_syncman_flag12,
1310       { "SM Flag12", "ecat.syncman_flag12",
1311       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag12), 0x00001000,
1312       "", HFILL }
1313       },
1314       { &hf_ecat_syncman_flag13,
1315       { "SM Flag13", "ecat.syncman_flag13",
1316       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag13), 0x00002000,
1317       "", HFILL }
1318       },
1319       { &hf_ecat_syncman_flag16,
1320       { "SM Flag16", "ecat.syncman_flag16",
1321       FT_BOOLEAN, 32, TFS(&tfs_ecat_syncman_flag16), 0x00010000,
1322       "", HFILL }
1323       },
1324       { &hf_ecat_fmmu,
1325       { "FMMU", "ecat.fmmu",
1326       FT_BYTES, BASE_NONE, NULL, 0x0,
1327       "", HFILL }
1328       },
1329       { &hf_ecat_fmmu_lstart,
1330       { "Log Start    ", "ecat.fmmu.lstart",
1331       FT_UINT32, BASE_HEX, NULL, 0x0,
1332       "", HFILL }
1333       },
1334       { &hf_ecat_fmmu_llen,
1335       { "Log Length   ", "ecat.fmmu.llen",
1336       FT_UINT16, BASE_HEX, NULL, 0x0,
1337       "", HFILL }
1338       },
1339       { &hf_ecat_fmmu_lstartbit,
1340       { "Log StartBit ", "ecat.fmmu.lstartbit",
1341       FT_UINT8, BASE_HEX, NULL, 0x0,
1342       "", HFILL }
1343       },
1344       { &hf_ecat_fmmu_lendbit,
1345       { "Log EndBit   ", "ecat.fmmu.lendbit",
1346       FT_UINT8, BASE_HEX, NULL, 0x0,
1347       "", HFILL }
1348       },
1349       { &hf_ecat_fmmu_pstart,
1350       { "Phys Start   ", "ecat.fmmu.pstart",
1351       FT_UINT8, BASE_HEX, NULL, 0x0,
1352       "", HFILL }
1353       },
1354       { &hf_ecat_fmmu_pstartbit,
1355       { "Phys StartBit", "ecat.fmmu.pstartbit",
1356       FT_UINT8, BASE_HEX, NULL, 0x0,
1357       "", HFILL }
1358       },
1359       { &hf_ecat_fmmu_type,
1360       { "FMMU Type    ", "ecat.fmmu.type",
1361       FT_UINT8, BASE_HEX, NULL, 0x0,
1362       "", HFILL }
1363       },
1364       { &hf_ecat_fmmu_typeread,
1365       { "Type", "ecat.fmmu.typeread",
1366       FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_typeread), 0x01,
1367       "", HFILL }
1368       },
1369       { &hf_ecat_fmmu_typewrite,
1370       { "Type", "ecat.fmmu.typewrite",
1371       FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_typewrite), 0x02,
1372       "", HFILL }
1373       },
1374       { &hf_ecat_fmmu_active,
1375       { "FMMU Active  ", "ecat.fmmu.active",
1376       FT_UINT8, BASE_HEX, NULL, 0x0,
1377       "", HFILL }
1378       },
1379       { &hf_ecat_fmmu_active0,
1380       { "Active", "ecat.fmmu.active0",
1381       FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_active), 0x01,
1382       "", HFILL }
1383       },
1384       { &hf_ecat_dc_diff_da,
1385       { "DC D-A", "ecat.dc.dif.da",
1386       FT_UINT32, BASE_DEC, NULL, 0x0,
1387       "", HFILL }
1388       },
1389       { &hf_ecat_dc_diff_bd,
1390       { "DC B-D", "ecat.dc.dif.bd",
1391       FT_UINT32, BASE_DEC, NULL, 0x0,
1392       "", HFILL }
1393       },
1394       { &hf_ecat_dc_diff_cb,
1395       { "DC C-B", "ecat.dc.dif.cb",
1396       FT_UINT32, BASE_DEC, NULL, 0x0,
1397       "", HFILL }
1398       },
1399       { &hf_ecat_dc_diff_cd,
1400       { "DC C-D", "ecat.dc.dif.cd",
1401       FT_UINT32, BASE_DEC, NULL, 0x0,
1402       "", HFILL }
1403       },
1404       { &hf_ecat_dc_diff_ba,
1405       { "DC B-A", "ecat.dc.dif.ba",
1406       FT_UINT32, BASE_DEC, NULL, 0x0,
1407       "", HFILL }
1408       },
1409       { &hf_ecat_dc_diff_ca,
1410       { "DC C-A", "ecat.dc.dif.ca",
1411       FT_UINT32, BASE_DEC, NULL, 0x0,
1412       "", HFILL }
1413       },
1414       { &hf_ecat_sub_dc_diff_da[0],
1415       { "DC D-A", "ecat.sub1.dc.dif.da",
1416       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1417       },
1418       { &hf_ecat_sub_dc_diff_da[1],
1419       { "DC D-A", "ecat.sub2.dc.dif.da",
1420       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1421       },
1422       { &hf_ecat_sub_dc_diff_da[2],
1423       { "DC D-A", "ecat.sub3.dc.dif.da",
1424       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1425       },
1426       { &hf_ecat_sub_dc_diff_da[3],
1427       { "DC D-A", "ecat.sub4.dc.dif.da",
1428       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1429       },
1430       { &hf_ecat_sub_dc_diff_da[4],
1431       { "DC D-A", "ecat.sub5.dc.dif.da",
1432       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1433       },
1434       { &hf_ecat_sub_dc_diff_da[5],
1435       { "DC D-A", "ecat.sub6.dc.dif.da",
1436       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1437       },
1438       { &hf_ecat_sub_dc_diff_da[6],
1439       { "DC D-A", "ecat.sub7.dc.dif.da",
1440       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1441       },
1442       { &hf_ecat_sub_dc_diff_da[7],
1443       { "DC D-A", "ecat.sub8.dc.dif.da",
1444       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1445       },
1446       { &hf_ecat_sub_dc_diff_da[8],
1447       { "DC D-A", "ecat.sub9.dc.dif.da",
1448       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1449       },
1450       { &hf_ecat_sub_dc_diff_da[9],
1451       { "DC D-A", "ecat.sub10.dc.dif.da",
1452       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1453       },
1454
1455       { &hf_ecat_sub_dc_diff_bd[0],
1456       { "DC B-C", "ecat.sub1.dc.dif.bd",
1457       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1458       },
1459       { &hf_ecat_sub_dc_diff_bd[1],
1460       { "DC B-C", "ecat.sub2.dc.dif.bd",
1461       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1462       },
1463       { &hf_ecat_sub_dc_diff_bd[2],
1464       { "DC B-C", "ecat.sub3.dc.dif.bd",
1465       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1466       },
1467       { &hf_ecat_sub_dc_diff_bd[3],
1468       { "DC B-C", "ecat.sub4.dc.dif.bd",
1469       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1470       },
1471       { &hf_ecat_sub_dc_diff_bd[4],
1472       { "DC B-C", "ecat.sub5.dc.dif.bd",
1473       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1474       },
1475       { &hf_ecat_sub_dc_diff_bd[5],
1476       { "DC B-C", "ecat.sub6.dc.dif.bd",
1477       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1478       },
1479       { &hf_ecat_sub_dc_diff_bd[6],
1480       { "DC B-C", "ecat.sub7.dc.dif.bd",
1481       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1482       },
1483       { &hf_ecat_sub_dc_diff_bd[7],
1484       { "DC B-C", "ecat.sub8.dc.dif.bd",
1485       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1486       },
1487       { &hf_ecat_sub_dc_diff_bd[8],
1488       { "DC B-C", "ecat.sub9.dc.dif.bd",
1489       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1490       },
1491       { &hf_ecat_sub_dc_diff_bd[9],
1492       { "DC B-D", "ecat.sub10.dc.dif.bd",
1493       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1494       },
1495
1496       { &hf_ecat_sub_dc_diff_cb[0],
1497       { "DC C-B", "ecat.sub1.dc.dif.cb",
1498       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1499       },
1500       { &hf_ecat_sub_dc_diff_cb[1],
1501       { "DC C-B", "ecat.sub2.dc.dif.cb",
1502       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1503       },
1504       { &hf_ecat_sub_dc_diff_cb[2],
1505       { "DC C-B", "ecat.sub3.dc.dif.cb",
1506       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1507       },
1508       { &hf_ecat_sub_dc_diff_cb[3],
1509       { "DC C-B", "ecat.sub4.dc.dif.cb",
1510       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1511       },
1512       { &hf_ecat_sub_dc_diff_cb[4],
1513       { "DC C-B", "ecat.sub5.dc.dif.cb",
1514       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1515       },
1516       { &hf_ecat_sub_dc_diff_cb[5],
1517       { "DC C-B", "ecat.sub6.dc.dif.cb",
1518       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1519       },
1520       { &hf_ecat_sub_dc_diff_cb[6],
1521       { "DC C-B", "ecat.sub7.dc.dif.cb",
1522       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1523       },
1524       { &hf_ecat_sub_dc_diff_cb[7],
1525       { "DC C-B", "ecat.sub8.dc.dif.cb",
1526       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1527       },
1528       { &hf_ecat_sub_dc_diff_cb[8],
1529       { "DC C-B", "ecat.sub9.dc.dif.cb",
1530       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1531       },
1532       { &hf_ecat_sub_dc_diff_cb[9],
1533       { "DC C-B", "ecat.sub10.dc.dif.cb",
1534       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1535       },
1536
1537       { &hf_ecat_sub_dc_diff_cd[0],
1538       { "DC C-D", "ecat.sub1.dc.dif.cd",
1539       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1540       },
1541       { &hf_ecat_sub_dc_diff_cd[1],
1542       { "DC C-D", "ecat.sub2.dc.dif.cd",
1543       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1544       },
1545       { &hf_ecat_sub_dc_diff_cd[2],
1546       { "DC C-D", "ecat.sub3.dc.dif.cd",
1547       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1548       },
1549       { &hf_ecat_sub_dc_diff_cd[3],
1550       { "DC C-D", "ecat.sub4.dc.dif.cd",
1551       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1552       },
1553       { &hf_ecat_sub_dc_diff_cd[4],
1554       { "DC C-D", "ecat.sub5.dc.dif.cd",
1555       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1556       },
1557       { &hf_ecat_sub_dc_diff_cd[5],
1558       { "DC C-D", "ecat.sub6.dc.dif.cd",
1559       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1560       },
1561       { &hf_ecat_sub_dc_diff_cd[6],
1562       { "DC C-D", "ecat.sub7.dc.dif.cd",
1563       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1564       },
1565       { &hf_ecat_sub_dc_diff_cd[7],
1566       { "DC C-D", "ecat.sub8.dc.dif.cd",
1567       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1568       },
1569       { &hf_ecat_sub_dc_diff_cd[8],
1570       { "DC C-D", "ecat.sub9.dc.dif.cd",
1571       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1572       },
1573       { &hf_ecat_sub_dc_diff_cd[9],
1574       { "DC C-D", "ecat.sub10.dc.dif.cd",
1575       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1576       },
1577
1578       { &hf_ecat_sub_dc_diff_ba[0],
1579       { "DC B-A", "ecat.sub1.dc.dif.ba",
1580       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1581       },
1582       { &hf_ecat_sub_dc_diff_ba[1],
1583       { "DC B-A", "ecat.sub2.dc.dif.ba",
1584       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1585       },
1586       { &hf_ecat_sub_dc_diff_ba[2],
1587       { "DC B-A", "ecat.sub3.dc.dif.ba",
1588       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1589       },
1590       { &hf_ecat_sub_dc_diff_ba[3],
1591       { "DC B-A", "ecat.sub4.dc.dif.ba",
1592       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1593       },
1594       { &hf_ecat_sub_dc_diff_ba[4],
1595       { "DC B-A", "ecat.sub5.dc.dif.ba",
1596       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1597       },
1598       { &hf_ecat_sub_dc_diff_ba[5],
1599       { "DC B-A", "ecat.sub6.dc.dif.ba",
1600       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1601       },
1602       { &hf_ecat_sub_dc_diff_ba[6],
1603       { "DC B-A", "ecat.sub7.dc.dif.ba",
1604       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1605       },
1606       { &hf_ecat_sub_dc_diff_ba[7],
1607       { "DC B-A", "ecat.sub8.dc.dif.ba",
1608       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1609       },
1610       { &hf_ecat_sub_dc_diff_ba[8],
1611       { "DC B-A", "ecat.sub9.dc.dif.ba",
1612       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1613       },
1614       { &hf_ecat_sub_dc_diff_ba[9],
1615       { "DC B-A", "ecat.sub10.dc.dif.ba",
1616       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1617       },
1618
1619       { &hf_ecat_sub_dc_diff_ca[0],
1620       { "DC C-A", "ecat.sub1.dc.dif.ca",
1621       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1622       },
1623       { &hf_ecat_sub_dc_diff_ca[1],
1624       { "DC C-A", "ecat.sub2.dc.dif.ca",
1625       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1626       },
1627       { &hf_ecat_sub_dc_diff_ca[2],
1628       { "DC C-A", "ecat.sub3.dc.dif.ca",
1629       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1630       },
1631       { &hf_ecat_sub_dc_diff_ca[3],
1632       { "DC C-A", "ecat.sub4.dc.dif.ca",
1633       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1634       },
1635       { &hf_ecat_sub_dc_diff_ca[4],
1636       { "DC C-A", "ecat.sub5.dc.dif.ca",
1637       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1638       },
1639       { &hf_ecat_sub_dc_diff_ca[5],
1640       { "DC C-A", "ecat.sub6.dc.dif.ca",
1641       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1642       },
1643       { &hf_ecat_sub_dc_diff_ca[6],
1644       { "DC C-A", "ecat.sub7.dc.dif.ca",
1645       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1646       },
1647       { &hf_ecat_sub_dc_diff_ca[7],
1648       { "DC C-A", "ecat.sub8.dc.dif.ca",
1649       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1650       },
1651       { &hf_ecat_sub_dc_diff_ca[8],
1652       { "DC C-A", "ecat.sub9.dc.dif.ca",
1653       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1654       },
1655       { &hf_ecat_sub_dc_diff_ca[9],
1656       { "DC C-A", "ecat.sub10.dc.dif.ca",
1657       FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1658       },
1659       { &hf_ecat_length_len,
1660       { "Length", "ecat.subframe.length",
1661       FT_UINT16, BASE_DEC, NULL, 0x07ff, "", HFILL}
1662       },
1663       { &hf_ecat_length_r,
1664       { "Reserved", "ecat.subframe.reserved",
1665       FT_UINT16, BASE_DEC, VALS(&ecat_subframe_reserved_vals), 0x3800, "", HFILL}
1666       },
1667       { &hf_ecat_length_c,
1668       { "Round trip", "ecat.subframe.circulating",
1669       FT_UINT16, BASE_DEC, VALS(&ecat_subframe_circulating_vals), 0x4000, "", HFILL}
1670       },
1671       { &hf_ecat_length_m,
1672       { "Last indicator", "ecat.subframe.more",
1673       FT_UINT16, BASE_DEC, VALS(&ecat_subframe_more_vals), 0x8000, "", HFILL}
1674       },
1675       { &hf_ecat_padding,
1676       { "Pad bytes", "ecat.subframe.pad_bytes",
1677       FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL}
1678       }
1679    };
1680
1681    static gint *ett[] =
1682    {
1683       &ett_ecat,
1684       &ett_ecat_header,
1685       &ett_ecat_syncman,
1686       &ett_ecat_syncflag,
1687       &ett_ecat_fmmu,
1688       &ett_ecat_fmmu_type,
1689       &ett_ecat_fmmu_active,
1690       &ett_ecat_dc,
1691       &ett_ecat_length,
1692       &ett_ecat_padding,
1693       &ett_ecat_datagram_subtree
1694    };
1695
1696    proto_ecat_datagram = proto_register_protocol("EtherCAT datagram(s)",
1697       "ECAT", "ecat");
1698    proto_register_field_array(proto_ecat_datagram, hf, array_length(hf));
1699    proto_register_subtree_array(ett, array_length(ett));
1700
1701    /* Sub dissector code */
1702    register_heur_dissector_list("ecat.data", &heur_subdissector_list);
1703 }
1704
1705 /* The registration hand-off routing */
1706 void proto_reg_handoff_ecat(void)
1707 {
1708    dissector_handle_t ecat_handle;
1709
1710    /* Register this dissector as a sub dissector to EtherCAT frame based on
1711       ether type. */
1712    ecat_handle = create_dissector_handle(dissect_ecat_datagram, proto_ecat_datagram);
1713    dissector_add("ecatf.type", 1 /* EtherCAT type */, ecat_handle);
1714
1715    ecat_mailbox_handle = find_dissector("ecat_mailbox");
1716 }