1 //--------------------------------------------------------------------------
2 // Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // iec104_parse_apdu.h author Jared Rittle <jared.rittle@cisco.com>
20 
21 #ifndef IEC104_PARSE_APCI_H
22 #define IEC104_PARSE_APCI_H
23 
24 #include <cstdint>
25 
26 void parseIec104ApciU(const struct Iec104ApciU* apci);
27 void parseIec104ApciS(const struct Iec104ApciS* apci);
28 void parseIec104ApciI(const struct Iec104ApciI* apci);
29 
30 
31 #define IEC104_ERROR -1
32 #define IEC104_START_BYTE 0x68
33 #define IEC104_APCI_HDR_LEN 2 // accounts for Start and Length
34 #define IEC104_APCI_TYPE_U_LEN 4
35 #define IEC104_APCI_TYPE_S_LEN 4
36 #define IEC104_APCI_TYPE_I_MIN_LEN 12
37 #define IEC104_APCI_TYPE_I_HDR_LEN 6
38 #define IEC104_CTX_NOT_ALLOWED 0
39 #define IEC104_CTX_ALLOWED 1
40 
41 
42 //
43 //
44 // Enums
45 //
46 //
47 
48 // Definition for the different APCI headers
49 // This allows us to make determinations on how to handle the fields following the first 1-2 bits
50 enum ApciTypeEnum
51 {
52     IEC104_NO_APCI     = -1,
53     IEC104_APCI_TYPE_I = 0,
54     IEC104_APCI_TYPE_S = 1,
55     IEC104_APCI_TYPE_U = 2,
56 };
57 
58 enum AsduTypeEnum
59 {
60     IEC104_NO_ASDU         =  0,     // placeholder for an error case
61     IEC104_ASDU_M_SP_NA_1  =  1,     // Single-point information
62     IEC104_ASDU_M_SP_TA_1  =  2,     // Single-point information with time tag
63     IEC104_ASDU_M_DP_NA_1  =  3,     // Double-point information
64     IEC104_ASDU_M_DP_TA_1  =  4,     // Double-point information with time tag
65     IEC104_ASDU_M_ST_NA_1  =  5,     // Step position information
66     IEC104_ASDU_M_ST_TA_1  =  6,     // Step position information with time tag
67     IEC104_ASDU_M_BO_NA_1  =  7,     // Bitstring of 32 bit
68     IEC104_ASDU_M_BO_TA_1  =  8,     // Bitstring of 32 bit with time tag
69     IEC104_ASDU_M_ME_NA_1  =  9,     // Measured value, normalized value
70     IEC104_ASDU_M_ME_TA_1  =  10,    // Measured value, normalized value with time tag
71     IEC104_ASDU_M_ME_NB_1  =  11,    // Measured value, scaled value
72     IEC104_ASDU_M_ME_TB_1  =  12,    // Measured value, scaled value wit time tag
73     IEC104_ASDU_M_ME_NC_1  =  13,    // Measured value, short floating point number
74     IEC104_ASDU_M_ME_TC_1  =  14,    // Measured value, short floating point number with time tag
75     IEC104_ASDU_M_IT_NA_1  =  15,    // Integrated totals
76     IEC104_ASDU_M_IT_TA_1  =  16,    // Integrated totals with time tag
77     IEC104_ASDU_M_EP_TA_1  =  17,    // Event of protection equipment with time tag
78     IEC104_ASDU_M_EP_TB_1  =  18,    // Packed start events of protection equipment with time tag
79     IEC104_ASDU_M_EP_TC_1  =  19,    // Packed output circuit information of protection equipment with time tag
80     IEC104_ASDU_M_PS_NA_1  =  20,    // Packed single point information with status change detection
81     IEC104_ASDU_M_ME_ND_1  =  21,    // Measured value, normalized value without quality descriptor
82     // 22-29 reserved
83     IEC104_ASDU_M_SP_TB_1  =  30,    // Single-point information with time tag CP56Time2a
84     IEC104_ASDU_M_DP_TB_1  =  31,    // Double-point information with time tag CP56Time2a
85     IEC104_ASDU_M_ST_TB_1  =  32,    // Step position information with time tag CP56Time2a
86     IEC104_ASDU_M_BO_TB_1  =  33,    // Bitstring of 32 bit with time tag CP56Time2a
87     IEC104_ASDU_M_ME_TD_1  =  34,    // Measured value, normalized value with time tag CP56Time2a
88     IEC104_ASDU_M_ME_TE_1  =  35,    // Measured value, scaled value with time tag CP56Time2a
89     IEC104_ASDU_M_ME_TF_1  =  36,    // Measured value, short floating point number with time tag CP56Time2a
90     IEC104_ASDU_M_IT_TB_1  =  37,    // Integrated totals with time tag CP56Time2a
91     IEC104_ASDU_M_EP_TD_1  =  38,    // Event of protection equipment with time tag CP56Time2a
92     IEC104_ASDU_M_EP_TE_1  =  39,    // Packed start events of protection equipment with time tag CP56Time2a
93     IEC104_ASDU_M_EP_TF_1  =  40,    // Packed output circuit information of protection equipment with time tag CP56Time2a
94     // 41-44 reserved
95     IEC104_ASDU_C_SC_NA_1  =  45,    // Single command
96     IEC104_ASDU_C_DC_NA_1  =  46,    // Double command
97     IEC104_ASDU_C_RC_NA_1  =  47,    // Regulating step command
98     IEC104_ASDU_C_SE_NA_1  =  48,    // Set-point Command, normalized value
99     IEC104_ASDU_C_SE_NB_1  =  49,    // Set-point Command, scaled value
100     IEC104_ASDU_C_SE_NC_1  =  50,    // Set-point Command, short floating point number
101     IEC104_ASDU_C_BO_NA_1  =  51,    // Bitstring 32 bit command
102     // 52-57 reserved
103     IEC104_ASDU_C_SC_TA_1  =  58,    // Single command with time tag CP56Time2a
104     IEC104_ASDU_C_DC_TA_1  =  59,    // Double command with time tag CP56Time2a
105     IEC104_ASDU_C_RC_TA_1  =  60,    // Regulating step command with time tag CP56Time2a
106     IEC104_ASDU_C_SE_TA_1  =  61,    // Set-point command with time tag CP56Time2a, normalized value
107     IEC104_ASDU_C_SE_TB_1  =  62,    // Set-point command with time tag CP56Time2a, scaled value
108     IEC104_ASDU_C_SE_TC_1  =  63,    // Set-point command with time tag CP56Time2a, short floating point number
109     IEC104_ASDU_C_BO_TA_1  =  64,    // Bitstring of 32 bit with time tag CP56Time2a
110     // 65-69 reserved
111     IEC104_ASDU_M_EI_NA_1  =  70,    // End of initialization
112     // 71-99 reserved
113     IEC104_ASDU_C_IC_NA_1  =  100,   // Interrogation command
114     IEC104_ASDU_C_CI_NA_1  =  101,   // Counter interrogation command
115     IEC104_ASDU_C_RD_NA_1  =  102,   // Read command
116     IEC104_ASDU_C_CS_NA_1  =  103,   // Clock synchronization command
117     IEC104_ASDU_C_TS_NA_1  =  104,   // Test command
118     IEC104_ASDU_C_RP_NA_1  =  105,   // Reset process command
119     IEC104_ASDU_C_CD_NA_1  =  106,   // Delay acquisition command
120     IEC104_ASDU_C_TS_TA_1  =  107,   // Test command with time tag CP56Time2a
121     // 108-109 reserved
122     IEC104_ASDU_P_ME_NA_1  =  110,   // Parameter of measured values, normalized value
123     IEC104_ASDU_P_ME_NB_1  =  111,   // Parameter of measured values, scaled value
124     IEC104_ASDU_P_ME_NC_1  =  112,   // Parameter of measured values, short floating point number
125     IEC104_ASDU_P_AC_NA_1  =  113,   // Parameter activation
126     // 114-119 reserved
127     IEC104_ASDU_F_FR_NA_1  =  120,   // File ready
128     IEC104_ASDU_F_SR_NA_1  =  121,   // Section ready
129     IEC104_ASDU_F_SC_NA_1  =  122,   // Call directory, select file, call file, call section
130     IEC104_ASDU_F_LS_NA_1  =  123,   // Last section, last segment
131     IEC104_ASDU_F_AF_NA_1  =  124,   // ACK file, ACK section
132     IEC104_ASDU_F_SG_NA_1  =  125,   // Single information object
133     IEC104_ASDU_F_DR_TA_1  =  126,   // Sequence of information elements in a single information object
134     IEC104_ASDU_F_SC_NB_1  =  127,   // QueryLog – Request archive file
135     // 128-256 reserved
136 };
137 
138 // Definition for the different transmission cause codes
139 enum CauseOfTransmissionEnum
140 {
141     IEC104_CAUSE_TX_NOT_USED                      = 0,     // not used
142     IEC104_CAUSE_TX_PER_CYC                       = 1,     // periodic, cyclic
143     IEC104_CAUSE_TX_BACK                          = 2,     // background scan3
144     IEC104_CAUSE_TX_SPONT                         = 3,     // spontaneous
145     IEC104_CAUSE_TX_INIT                           = 4,     // initialized
146     IEC104_CAUSE_TX_REQ                            = 5,     // request or requested
147     IEC104_CAUSE_TX_ACT                           = 6,     // activation
148     IEC104_CAUSE_TX_ACTCON                        = 7,     // activation confirmation
149     IEC104_CAUSE_TX_DEACT                         = 8,     // deactivation
150     IEC104_CAUSE_TX_DEACTCON                      = 9,     // deactivation confirmation
151     IEC104_CAUSE_TX_ACTTERM                       = 10,    // activation termination
152     IEC104_CAUSE_TX_RETREM                        = 11,    // return information caused by a remote command
153     IEC104_CAUSE_TX_RETLOC                         = 12,    // return information caused by a local command
154     IEC104_CAUSE_TX_FILE                          = 13,    // file transfer
155     IEC104_CAUSE_TX_RES14                         = 14,    // 14-19 reserved
156     IEC104_CAUSE_TX_RES15                         = 15,    // 14-19 reserved
157     IEC104_CAUSE_TX_RES16                         = 16,    // 14-19 reserved
158     IEC104_CAUSE_TX_RES17                         = 17,    // 14-19 reserved
159     IEC104_CAUSE_TX_RES18                         = 18,    // 14-19 reserved
160     IEC104_CAUSE_TX_RES19                         = 19,    // 14-19 reserved
161     IEC104_CAUSE_TX_INROGEN                       = 20,    // interrogated by station interrogation
162     IEC104_CAUSE_TX_INRO1                         = 21,    // interrogated by group 1 interrogation
163     IEC104_CAUSE_TX_INRO2                         = 22,    // interrogated by group 2 interrogation
164     IEC104_CAUSE_TX_INRO3                         = 23,    // interrogated by group 3 interrogation
165     IEC104_CAUSE_TX_INRO4                         = 24,    // interrogated by group 4 interrogation
166     IEC104_CAUSE_TX_INRO5                         = 25,    // interrogated by group 5 interrogation
167     IEC104_CAUSE_TX_INRO6                         = 26,    // interrogated by group 6 interrogation
168     IEC104_CAUSE_TX_INRO7                         = 27,    // interrogated by group 7 interrogation
169     IEC104_CAUSE_TX_INRO8                         = 28,    // interrogated by group 8 interrogation
170     IEC104_CAUSE_TX_INRO9                         = 29,    // interrogated by group 9 interrogation
171     IEC104_CAUSE_TX_INRO10                        = 30,    // interrogated by group 10 interrogation
172     IEC104_CAUSE_TX_INRO11                        = 31,    // interrogated by group 11 interrogation
173     IEC104_CAUSE_TX_INRO12                        = 32,    // interrogated by group 12 interrogation
174     IEC104_CAUSE_TX_INRO13                        = 33,    // interrogated by group 13 interrogation
175     IEC104_CAUSE_TX_INRO14                        = 34,    // interrogated by group 14 interrogation
176     IEC104_CAUSE_TX_INRO15                        = 35,    // interrogated by group 15 interrogation
177     IEC104_CAUSE_TX_INRO16                        = 36,    // interrogated by group 16 interrogation
178     IEC104_CAUSE_TX_REQCOGEN                      = 37,    // requested by general counter request
179     IEC104_CAUSE_TX_REQCO1                        = 38,    // requested by group 1 counter request
180     IEC104_CAUSE_TX_REQCO2                        = 39,    // requested by group 2 counter request
181     IEC104_CAUSE_TX_REQCO3                        = 40,    // requested by group 3 counter request
182     IEC104_CAUSE_TX_REQCO4                        = 41,    // requested by group 4 counter request
183     IEC104_CAUSE_TX_RES42                         = 42,    // 42-43 reserved
184     IEC104_CAUSE_TX_RES43                         = 43,    // 42-43 reserved
185     IEC104_CAUSE_TX_UNKNOWN_TYPE_ID               = 44,    // unknown type identification
186     IEC104_CAUSE_TX_UNKNOWN_CAUSE_OF_TX           = 45,    // unknown cause of transmission
187     IEC104_CAUSE_TX_UNKNOWN_COMMON_ADDR_OF_ASDU   = 46,    // unknown common address of ASDU
188     IEC104_CAUSE_TX_UNKNOWN_IOA                   = 47,    // unknown information object address
189     IEC104_CAUSE_TX_RES48                         = 48,    // 48-63 reserved
190     IEC104_CAUSE_TX_RES49                         = 49,    // 48-63 reserved
191     IEC104_CAUSE_TX_RES50                         = 50,    // 48-63 reserved
192     IEC104_CAUSE_TX_RES51                         = 51,    // 48-63 reserved
193     IEC104_CAUSE_TX_RES52                         = 52,    // 48-63 reserved
194     IEC104_CAUSE_TX_RES53                         = 53,    // 48-63 reserved
195     IEC104_CAUSE_TX_RES54                         = 54,    // 48-63 reserved
196     IEC104_CAUSE_TX_RES55                         = 55,    // 48-63 reserved
197     IEC104_CAUSE_TX_RES56                         = 56,    // 48-63 reserved
198     IEC104_CAUSE_TX_RES57                         = 57,    // 48-63 reserved
199     IEC104_CAUSE_TX_RES58                         = 58,    // 48-63 reserved
200     IEC104_CAUSE_TX_RES59                         = 59,    // 48-63 reserved
201     IEC104_CAUSE_TX_RES60                         = 60,    // 48-63 reserved
202     IEC104_CAUSE_TX_RES61                         = 61,    // 48-63 reserved
203     IEC104_CAUSE_TX_RES62                         = 62,    // 48-63 reserved
204     IEC104_CAUSE_TX_RES63                         = 63,    // 48-63 reserved
205 };
206 
207 enum StructureQualifierEnum
208 {
209     IEC104_SQ_FALSE  = 0,
210     IEC104_SQ_TRUE   = 1,
211 };
212 
213 
214 
215 
216 //
217 //
218 // Structs
219 //
220 //
221 
222 //
223 // Generic structs
224 //
225 
226 // struct Iec104To help determine what type of APCI is in use
227 struct Iec104GenericApci
228 {
229     uint8_t start;
230     uint8_t length;
231     uint8_t apciTypeMajor : 1;
232     uint8_t apciTypeMinor : 1;
233     uint8_t reserved : 6;
234 }__attribute__((packed));
235 
236 
237 //
238 // ASDU Information Object Structs
239 //
240 
241 struct Iec104VariableStructureQualifierType
242 {
243     uint8_t numberOfElements : 7;
244     uint8_t sq : 1;
245 }__attribute__((packed));
246 
247 // This structure does not require the OA, but it seems to be used in all traffic seen so far
248 struct Iec104CauseOfTransmissionType
249 {
250     uint8_t causeOfTransmission : 6;
251     uint8_t pn : 1;
252     uint8_t test : 1;
253     uint8_t oa;
254 }__attribute__((packed));
255 
256 // COI: Cause of Initialization Structure
257 struct Iec104CoiType
258 {
259     uint8_t ui : 7;
260     uint8_t bs : 1;
261 }__attribute__((packed));
262 
263 // QOI: Qualifier of Interrogation Structure
264 struct Iec104QoiType
265 {
266     uint8_t qoi;
267 }__attribute__((packed));
268 
269 // QCC: Qualifier of Counter Interrogation Command Structure
270 struct Iec104QccType
271 {
272     uint8_t rqt : 6;
273     uint8_t frz : 2;
274 }__attribute__((packed));
275 
276 // QPM: Qualifier of Parameter of Measured Values Structure
277 struct Iec104QpmType
278 {
279     uint8_t kpa : 6;
280     uint8_t lpc : 1;
281     uint8_t pop : 1;
282 }__attribute__((packed));
283 
284 // QPA: Qualifier of Parameter Activation Structure
285 struct Iec104QpaType
286 {
287     uint8_t qpa;
288 }__attribute__((packed));
289 
290 // QOC: Qualifier of Command Structure
291 // This doesn't add up to 8, but that is expected
292 // This struct gets used in fields that have 2 preceding bits
293 struct Iec104QocType
294 {
295     uint8_t qu : 5;
296     uint8_t se : 1;
297 }__attribute__((packed));
298 
299 // QRP: Qualifier of Reset Process Structure
300 struct Iec104QrpType
301 {
302     uint8_t qrp;
303 }__attribute__((packed));
304 
305 // FRQ: File Ready Qualifier Structure
306 struct Iec104FrqType
307 {
308     uint8_t ui : 7;
309     uint8_t bs : 1;
310 }__attribute__((packed));
311 
312 // SRQ: Section Ready Qualifier Structure
313 struct Iec104SrqType
314 {
315     uint8_t ui : 7;
316     uint8_t bs : 1;
317 }__attribute__((packed));
318 
319 // SCQ: Select and Call Qualifier Structure
320 struct Iec104ScqType
321 {
322     uint8_t ui1 : 4;
323     uint8_t ui2 : 4;
324 }__attribute__((packed));
325 
326 // LSQ: Last Section or Segment Qualifier Structure
327 struct Iec104LsqType
328 {
329     uint8_t lsq;
330 }__attribute__((packed));
331 
332 // AFQ: Acknowledge File or Section Qualifier Structure
333 struct Iec104AfqType
334 {
335     uint8_t ui1 : 4;
336     uint8_t ui2 : 4;
337 }__attribute__((packed));
338 
339 // Common Address of ASDU Structure
340 // This structure does not require the high octet, but it seems to be
341 //  used in all traffic seen so far
342 struct Iec104CommonAddressOfAsduType
343 {
344     uint16_t commonAddress;
345 }__attribute__((packed));
346 
347 // Information Object Address One Octet Structure
348 struct Iec104InformationObjectAddressOneOctetType
349 {
350     uint8_t informationObjectAddress;
351 }__attribute__((packed));
352 
353 // Information Object Address Two Octet Structure
354 struct Iec104InformationObjectAddressTwoOctetType
355 {
356     uint8_t informationObjectAddress[2];
357 }__attribute__((packed));
358 
359 // Information Object Address Three Octet Structure
360 struct Iec104InformationObjectAddressThreeOctetType
361 {
362     uint8_t informationObjectAddress[3];
363 }__attribute__((packed));
364 
365 // SIQ: Single Point Information with Quality Descriptor Structure
366 struct Iec104SiqType
367 {
368     uint8_t spi : 1;
369     uint8_t reserved : 3;
370     uint8_t bl : 1;
371     uint8_t sb : 1;
372     uint8_t nt : 1;
373     uint8_t iv : 1;
374 }__attribute__((packed));
375 
376 // DIQ: Double Point Information with Quality Descriptor Structure
377 struct Iec104DiqType
378 {
379     uint8_t dpi : 2;
380     uint8_t reserved : 2;
381     uint8_t bl : 1;
382     uint8_t sb : 1;
383     uint8_t nt : 1;
384     uint8_t iv : 1;
385 }__attribute__((packed));
386 
387 // QDS: Quality Descriptor Structure
388 struct Iec104QdsType
389 {
390     uint8_t ov : 1;
391     uint8_t reserved : 3;
392     uint8_t bl : 1;
393     uint8_t sb : 1;
394     uint8_t nt : 1;
395     uint8_t iv : 1;
396 }__attribute__((packed));
397 
398 // QDP: Quality Descriptor for Events of Protection Equipment Structure
399 struct Iec104QdpType
400 {
401     uint8_t reserved : 3;
402     uint8_t ei : 1;
403     uint8_t bl : 1;
404     uint8_t sb : 1;
405     uint8_t nt : 1;
406     uint8_t iv : 1;
407 }__attribute__((packed));
408 
409 // VTI: Value with Transient State Indication Structure
410 struct Iec104VtiType
411 {
412     uint8_t value : 7;
413     uint8_t t : 1;
414 }__attribute__((packed));
415 
416 // NVA: Normalized Value Structure
417 struct Iec104NvaType
418 {
419     uint16_t value;
420 }__attribute__((packed));
421 
422 // SVA: Scaled Value Structure
423 struct Iec104SvaType
424 {
425     uint16_t value;
426 }__attribute__((packed));
427 
428 // IEEE_STD_754: Short Floating Point Number Structure
429 struct Iec104IeeeStd754Type
430 {
431     uint32_t ieeeStd754;
432 }__attribute__((packed));
433 
434 // BCR: Binary Counter Reading Structure
435 struct Iec104BcrType
436 {
437     uint32_t value;
438     uint8_t sequenceNumber : 5;
439     uint8_t cy : 1;
440     uint8_t ca : 1;
441     uint8_t iv : 1;
442 }__attribute__((packed));
443 
444 // SEP: Single Event of Protection Equipment Structure
445 struct Iec104SepType
446 {
447     uint8_t es : 2;
448     uint8_t reserved : 1;
449     uint8_t ei : 1;
450     uint8_t bl : 1;
451     uint8_t sb : 1;
452     uint8_t nt : 1;
453     uint8_t iv : 1;
454 }__attribute__((packed));
455 
456 // SPE: Start Event of Protection Equipment Structure
457 struct Iec104SpeType
458 {
459     uint8_t gs : 1;
460     uint8_t sl1 : 1;
461     uint8_t sl2 : 1;
462     uint8_t sl3 : 1;
463     uint8_t sie : 1;
464     uint8_t srd : 1;
465     uint8_t reserved : 2;
466 }__attribute__((packed));
467 
468 // OCI: Output Circuit Information Structure
469 struct Iec104OciType
470 {
471     uint8_t gc : 1;
472     uint8_t cl1 : 1;
473     uint8_t cl2 : 1;
474     uint8_t cl3 : 1;
475     uint8_t reserved : 4;
476 }__attribute__((packed));
477 
478 // BSI: Binary State Information Structure
479 struct Iec104BsiType
480 {
481     uint32_t bitstring;
482 }__attribute__((packed));
483 
484 // FBP: Fixed Test Bit Pattern Structure
485 struct Iec104FbpType
486 {
487     uint16_t fixedTestBitPattern;
488 }__attribute__((packed));
489 
490 // SCO: Single Command Structure
491 struct Iec104ScoType
492 {
493     uint8_t scs : 1;
494     uint8_t reserved : 1;
495     uint8_t qu : 5;
496     uint8_t se : 1;
497 }__attribute__((packed));
498 
499 // DCO: Double Command Structure
500 struct Iec104DcoType
501 {
502     uint8_t dcs : 2;
503     uint8_t qu : 5;
504     uint8_t se : 1;
505 }__attribute__((packed));
506 
507 // RCO: Regulating Step Command Structure
508 struct Iec104RcoType
509 {
510     uint8_t rcs : 2;
511     uint8_t qu : 5;
512     uint8_t se : 1;
513 }__attribute__((packed));
514 
515 // Time2a Milliseconds Structure
516 struct Iec104Time2aMillisecondsType
517 {
518     uint16_t milliseconds;
519 }__attribute__((packed));
520 
521 // Time2a IVResMinute Structure
522 struct Iec104Time2aIvresminuteType
523 {
524     uint8_t minutes : 6;
525     uint8_t res : 1;
526     uint8_t iv : 1;
527 }__attribute__((packed));
528 
529 // Time2a SURes2Hour Structure
530 struct Iec104Time2aSures2hourType
531 {
532     uint8_t hours : 5;
533     uint8_t res2 : 2;
534     uint8_t su : 1;
535 }__attribute__((packed));
536 
537 // Time2a DOWDay Structure
538 struct Iec104Time2aDowdayType
539 {
540     uint8_t dayOfMonth : 5;
541     uint8_t dayOfWeek : 3;
542 }__attribute__((packed));
543 
544 // Time2a Res3Month Structure
545 struct Iec104Time2aRes3monthType
546 {
547     uint8_t month : 4;
548     uint8_t res3 : 4;
549 }__attribute__((packed));
550 
551 // Time2a Res4Year Structure
552 struct Iec104Time2aRes4yearType
553 {
554     uint8_t year : 7;
555     uint8_t res4 : 1;
556 }__attribute__((packed));
557 
558 // CP56Time2a Structure
559 struct Iec104Cp56Time2aType
560 {
561     Iec104Time2aMillisecondsType milliseconds;
562     Iec104Time2aIvresminuteType ivresminute;
563     Iec104Time2aSures2hourType sures2hour;
564     Iec104Time2aDowdayType dowday;
565     Iec104Time2aRes3monthType res3month;
566     Iec104Time2aRes4yearType res4year;
567 }__attribute__((packed));
568 
569 // Cp24Time2a Structure
570 struct Iec104Cp24Time2aType
571 {
572     Iec104Time2aMillisecondsType milliseconds;
573     Iec104Time2aIvresminuteType ivresminute;
574 }__attribute__((packed));
575 
576 // Cp16Time2a Structure
577 struct Iec104Cp16Time2aType
578 {
579     Iec104Time2aMillisecondsType milliseconds;
580 }__attribute__((packed));
581 
582 // NOF: Name of File Structure
583 struct Iec104NofType
584 {
585     uint16_t nameOfFile;
586 }__attribute__((packed));
587 
588 // NOS: Name of Section Structure
589 struct Iec104NosType
590 {
591     uint8_t nameOfSection;
592 }__attribute__((packed));
593 
594 // LOF: Length of File or Section Structure
595 struct Iec104LofType
596 {
597     uint8_t lengthOfFile[3];
598 }__attribute__((packed));
599 
600 // LOS: Length of Segment Structure
601 struct Iec104LosType
602 {
603     uint8_t lengthOfSegment;
604 }__attribute__((packed));
605 
606 // CHS: Checksum Structure
607 struct Iec104ChsType
608 {
609     uint8_t chs;
610 }__attribute__((packed));
611 
612 // SOF: Status of File Structure
613 // need to prepend `sof` tag on here since `for` is a reserved word
614 // doing it for the rest for consistency
615 struct Iec104SofType
616 {
617     uint8_t sofStatus : 5;
618     uint8_t sofLfd : 1;
619     uint8_t sofFor : 1;
620     uint8_t sofFa : 1;
621 }__attribute__((packed));
622 
623 // QOS: Qualifier of Set Point Command Structure
624 struct Iec104QosType
625 {
626     uint8_t ql : 7;
627     uint8_t se : 1;
628 }__attribute__((packed));
629 
630 // SCD: Status + Status Change Detection Structure
631 struct Iec104ScdType
632 {
633     uint16_t st;
634     uint16_t cd;
635 }__attribute__((packed));
636 
637 // TSC: Test Sequence Counter
638 struct Iec104TscType
639 {
640     uint16_t tsc;
641 }__attribute__((packed));
642 
643 // Segment: Segment type
644 struct Iec104SegmentType
645 {
646     uint8_t segment;
647 }__attribute__((packed));
648 
649 // Information Element
650 struct Iec104InformationElementType
651 {
652     Iec104NofType nameOfFileOrSubdirectory;
653     Iec104LofType lengthOfFile;
654     Iec104SofType sof;
655     Iec104Cp56Time2aType creationTimeOfFile;
656 }__attribute__((packed));
657 
658 
659 //
660 //
661 // ASDU structs
662 //
663 //
664 
665 //
666 // ASDUs for process information in monitor direction
667 //
668 
669 // ASDU Type M_SP_NA_1
670 // Ident 1
671 // Single-point information
672 
673 struct Iec104M_SP_NA_1_IO_Subgroup
674 {
675     Iec104SiqType siq;
676 }__attribute__((packed));
677 
678 struct Iec104M_SP_NA_1_IO_Group
679 {
680     Iec104InformationObjectAddressThreeOctetType ioa;
681     Iec104M_SP_NA_1_IO_Subgroup subgroup;
682 }__attribute__((packed));
683 
684 
685 // ASDU Type M_SP_TA_1
686 // Ident 2
687 // Single-point information with time tag
688 
689 struct Iec104M_SP_TA_1_IO_Subgroup
690 {
691     Iec104SiqType siq;
692     Iec104Cp24Time2aType threeOctetBinaryTime;
693 }__attribute__((packed));
694 
695 struct Iec104M_SP_TA_1_IO_Group
696 {
697     Iec104InformationObjectAddressThreeOctetType ioa;
698     Iec104M_SP_TA_1_IO_Subgroup subgroup;
699 }__attribute__((packed));
700 
701 
702 // ASDU Type M_DP_NA_1
703 // Ident 3
704 // Double-point information
705 
706 struct Iec104M_DP_NA_1_IO_Subgroup
707 {
708     Iec104DiqType diq;
709 }__attribute__((packed));
710 
711 struct Iec104M_DP_NA_1_IO_Group
712 {
713     Iec104InformationObjectAddressThreeOctetType ioa;
714     Iec104M_DP_NA_1_IO_Subgroup subgroup;
715 }__attribute__((packed));
716 
717 
718 // ASDU Type M_DP_TA_1
719 // Ident 4
720 // Double-point information with time tag
721 
722 struct Iec104M_DP_TA_1_IO_Subgroup
723 {
724     Iec104DiqType diq;
725     Iec104Cp24Time2aType threeOctetBinaryTime;
726 }__attribute__((packed));
727 
728 struct Iec104M_DP_TA_1_IO_Group
729 {
730     Iec104InformationObjectAddressThreeOctetType ioa;
731     Iec104M_DP_TA_1_IO_Subgroup subgroup;
732 }__attribute__((packed));
733 
734 
735 // ASDU Type M_ST_NA_1
736 // Ident 5
737 // Step position information
738 
739 struct Iec104M_ST_NA_1_IO_Subgroup
740 {
741     Iec104VtiType vti;
742     Iec104QdsType qds;
743 }__attribute__((packed));
744 
745 struct Iec104M_ST_NA_1_IO_Group
746 {
747     Iec104InformationObjectAddressThreeOctetType ioa;
748     Iec104M_ST_NA_1_IO_Subgroup subgroup;
749 }__attribute__((packed));
750 
751 
752 // ASDU Type M_ST_TA_1
753 // Ident 6
754 // Step position information with time tag
755 
756 struct Iec104M_ST_TA_1_IO_Subgroup
757 {
758     Iec104VtiType vti;
759     Iec104QdsType qds;
760     Iec104Cp24Time2aType threeOctetBinaryTime;
761 }__attribute__((packed));
762 
763 struct Iec104M_ST_TA_1_IO_Group
764 {
765     Iec104InformationObjectAddressThreeOctetType ioa;
766     Iec104M_ST_TA_1_IO_Subgroup subgroup;
767 }__attribute__((packed));
768 
769 
770 // ASDU Type M_BO_NA_1
771 // Ident 7
772 // Bitstring of 32 bit
773 
774 struct Iec104M_BO_NA_1_IO_Subgroup
775 {
776     Iec104BsiType bsi;
777     Iec104QdsType qds;
778 }__attribute__((packed));
779 
780 struct Iec104M_BO_NA_1_IO_Group
781 {
782     Iec104InformationObjectAddressThreeOctetType ioa;
783     Iec104M_BO_NA_1_IO_Subgroup subgroup;
784 }__attribute__((packed));
785 
786 
787 // ASDU Type M_BO_TA_1
788 // Ident 8
789 // Bitstring of 32 bit with time tag
790 
791 struct Iec104M_BO_TA_1_IO_Subgroup
792 {
793     Iec104BsiType bsi;
794     Iec104QdsType qds;
795     Iec104Cp24Time2aType threeOctetBinaryTime;
796 }__attribute__((packed));
797 
798 struct Iec104M_BO_TA_1_IO_Group
799 {
800     Iec104InformationObjectAddressThreeOctetType ioa;
801     Iec104M_BO_TA_1_IO_Subgroup subgroup;
802 }__attribute__((packed));
803 
804 
805 // ASDU Type M_ME_NA_1
806 // Ident 9
807 // Measured value, normalized value
808 
809 struct Iec104M_ME_NA_1_IO_Subgroup
810 {
811     Iec104NvaType nva;
812     Iec104QdsType qds;
813 }__attribute__((packed));
814 
815 struct Iec104M_ME_NA_1_IO_Group
816 {
817     Iec104InformationObjectAddressThreeOctetType ioa;
818     Iec104M_ME_NA_1_IO_Subgroup subgroup;
819 }__attribute__((packed));
820 
821 
822 // ASDU Type M_ME_TA_1
823 // Ident 10
824 // Measured value, normalized value with time tag
825 
826 struct Iec104M_ME_TA_1_IO_Subgroup
827 {
828     Iec104NvaType nva;
829     Iec104QdsType qds;
830     Iec104Cp24Time2aType threeOctetBinaryTime;
831 }__attribute__((packed));
832 
833 struct Iec104M_ME_TA_1_IO_Group
834 {
835     Iec104InformationObjectAddressThreeOctetType ioa;
836     Iec104M_ME_TA_1_IO_Subgroup subgroup;
837 }__attribute__((packed));
838 
839 
840 // ASDU Type M_ME_NB_1
841 // Ident 11
842 // Measured value, scaled value
843 
844 struct Iec104M_ME_NB_1_IO_Subgroup
845 {
846     Iec104SvaType sva;
847     Iec104QdsType qds;
848 }__attribute__((packed));
849 
850 struct Iec104M_ME_NB_1_IO_Group
851 {
852     Iec104InformationObjectAddressThreeOctetType ioa;
853     Iec104M_ME_NB_1_IO_Subgroup subgroup;
854 }__attribute__((packed));
855 
856 
857 // ASDU Type M_ME_TB_1
858 // Ident 12
859 // Measured value, scaled value wit time tag
860 
861 struct Iec104M_ME_TB_1_IO_Subgroup
862 {
863     Iec104SvaType sva;
864     Iec104QdsType qds;
865     Iec104Cp24Time2aType threeOctetBinaryTime;
866 }__attribute__((packed));
867 
868 struct Iec104M_ME_TB_1_IO_Group
869 {
870     Iec104InformationObjectAddressThreeOctetType ioa;
871     Iec104M_ME_TB_1_IO_Subgroup subgroup;
872 }__attribute__((packed));
873 
874 
875 // ASDU Type M_ME_NC_1
876 // Ident 13
877 // Measured value, short floating point number
878 
879 struct Iec104M_ME_NC_1_IO_Subgroup
880 {
881     Iec104IeeeStd754Type ieeeStd754;
882     Iec104QdsType qds;
883 }__attribute__((packed));
884 
885 struct Iec104M_ME_NC_1_IO_Group
886 {
887     Iec104InformationObjectAddressThreeOctetType ioa;
888     Iec104M_ME_NC_1_IO_Subgroup subgroup;
889 }__attribute__((packed));
890 
891 
892 // ASDU Type M_ME_TC_1
893 // Ident 14
894 // Measured value, short floating point number with time tag
895 
896 struct Iec104M_ME_TC_1_IO_Subgroup
897 {
898     Iec104IeeeStd754Type ieeeStd754;
899     Iec104QdsType qds;
900     Iec104Cp24Time2aType threeOctetBinaryTime;
901 }__attribute__((packed));
902 
903 struct Iec104M_ME_TC_1_IO_Group
904 {
905     Iec104InformationObjectAddressThreeOctetType ioa;
906     Iec104M_ME_TC_1_IO_Subgroup subgroup;
907 }__attribute__((packed));
908 
909 
910 // ASDU Type M_IT_NA_1
911 // Ident 15
912 // Integrated totals
913 
914 struct Iec104M_IT_NA_1_IO_Subgroup
915 {
916     Iec104BcrType bcr;
917 }__attribute__((packed));
918 
919 struct Iec104M_IT_NA_1_IO_Group
920 {
921     Iec104InformationObjectAddressThreeOctetType ioa;
922     Iec104M_IT_NA_1_IO_Subgroup subgroup;
923 }__attribute__((packed));
924 
925 
926 // ASDU Type M_IT_TA_1
927 // Ident 16
928 // Integrated totals with time tag
929 
930 struct Iec104M_IT_TA_1_IO_Subgroup
931 {
932     Iec104BcrType bcr;
933     Iec104Cp24Time2aType threeOctetBinaryTime;
934 }__attribute__((packed));
935 
936 struct Iec104M_IT_TA_1_IO_Group
937 {
938     Iec104InformationObjectAddressThreeOctetType ioa;
939     Iec104M_IT_TA_1_IO_Subgroup subgroup;
940 }__attribute__((packed));
941 
942 
943 // ASDU Type M_EP_TA_1
944 // Ident 17
945 // Event of protection equipment with time tag
946 
947 struct Iec104M_EP_TA_1_IO_Subgroup
948 {
949     Iec104SepType sep;
950     Iec104Cp16Time2aType elapsedTime;
951     Iec104Cp24Time2aType threeOctetBinaryTime;
952 }__attribute__((packed));
953 
954 struct Iec104M_EP_TA_1_IO_Group
955 {
956     Iec104InformationObjectAddressThreeOctetType ioa;
957     Iec104M_EP_TA_1_IO_Subgroup subgroup;
958 }__attribute__((packed));
959 
960 
961 // ASDU Type M_EP_TB_1
962 // Ident 18
963 // Packed start events of protection equipment with time tag
964 
965 struct Iec104M_EP_TB_1_IO_Subgroup
966 {
967     Iec104SpeType spe;
968     Iec104QdpType qdp;
969     Iec104Cp16Time2aType relayDurationTime;
970     Iec104Cp24Time2aType threeOctetBinaryTime;
971 }__attribute__((packed));
972 
973 struct Iec104M_EP_TB_1_IO_Group
974 {
975     Iec104InformationObjectAddressThreeOctetType ioa;
976     Iec104M_EP_TB_1_IO_Subgroup subgroup;
977 }__attribute__((packed));
978 
979 
980 // ASDU Type M_EP_TC_1
981 // Ident 19
982 // Packed output circuit information of protection equipment with time tag
983 
984 struct Iec104M_EP_TC_1_IO_Subgroup
985 {
986     Iec104OciType oci;
987     Iec104QdpType qdp;
988     Iec104Cp16Time2aType relayOperatingTime;
989     Iec104Cp24Time2aType threeOctetBinaryTime;
990 }__attribute__((packed));
991 
992 struct Iec104M_EP_TC_1_IO_Group
993 {
994     Iec104InformationObjectAddressThreeOctetType ioa;
995     Iec104M_EP_TC_1_IO_Subgroup subgroup;
996 }__attribute__((packed));
997 
998 
999 // ASDU Type M_PS_NA_1
1000 // Ident 20
1001 // Packed single point information with status change detection
1002 
1003 struct Iec104M_PS_NA_1_IO_Subgroup
1004 {
1005     Iec104ScdType scd;
1006     Iec104QdsType qds;
1007 }__attribute__((packed));
1008 
1009 struct Iec104M_PS_NA_1_IO_Group
1010 {
1011     Iec104InformationObjectAddressThreeOctetType ioa;
1012     Iec104M_PS_NA_1_IO_Subgroup subgroup;
1013 }__attribute__((packed));
1014 
1015 
1016 // ASDU Type M_ME_ND_1
1017 // Ident 21
1018 // Measured value, normalized value without quality descriptor
1019 
1020 struct Iec104M_ME_ND_1_IO_Subgroup
1021 {
1022     Iec104NvaType nva;
1023 }__attribute__((packed));
1024 
1025 struct Iec104M_ME_ND_1_IO_Group
1026 {
1027     Iec104InformationObjectAddressThreeOctetType ioa;
1028     Iec104M_ME_ND_1_IO_Subgroup subgroup;
1029 }__attribute__((packed));
1030 
1031 
1032 // ASDU Type M_SP_TB_1
1033 // Ident 30
1034 // Single-point information with time tag CP56Time2a
1035 
1036 struct Iec104M_SP_TB_1_IO_Subgroup
1037 {
1038     Iec104SiqType siq;
1039     Iec104Cp56Time2aType sevenOctetBinaryTime;
1040 }__attribute__((packed));
1041 
1042 struct Iec104M_SP_TB_1_IO_Group
1043 {
1044     Iec104InformationObjectAddressThreeOctetType ioa;
1045     Iec104M_SP_TB_1_IO_Subgroup subgroup;
1046 }__attribute__((packed));
1047 
1048 
1049 // ASDU Type M_DP_TB_1
1050 // Ident 31
1051 // Double-point information with time tag CP56Time2a
1052 
1053 struct Iec104M_DP_TB_1_IO_Subgroup
1054 {
1055     Iec104DiqType diq;
1056     Iec104Cp56Time2aType sevenOctetBinaryTime;
1057 }__attribute__((packed));
1058 
1059 struct Iec104M_DP_TB_1_IO_Group
1060 {
1061     Iec104InformationObjectAddressThreeOctetType ioa;
1062     Iec104M_DP_TB_1_IO_Subgroup subgroup;
1063 }__attribute__((packed));
1064 
1065 
1066 // ASDU Type M_ST_TB_1
1067 // Ident 32
1068 // Step position information with time tag CP56Time2a
1069 
1070 struct Iec104M_ST_TB_1_IO_Subgroup
1071 {
1072     Iec104VtiType vti;
1073     Iec104QdsType qds;
1074     Iec104Cp56Time2aType sevenOctetBinaryTime;
1075 }__attribute__((packed));
1076 
1077 struct Iec104M_ST_TB_1_IO_Group
1078 {
1079     Iec104InformationObjectAddressThreeOctetType ioa;
1080     Iec104M_ST_TB_1_IO_Subgroup subgroup;
1081 }__attribute__((packed));
1082 
1083 
1084 // ASDU Type M_BO_TB_1
1085 // Ident 33
1086 // Bitstring of 32 bit with time tag CP56Time2a
1087 
1088 struct Iec104M_BO_TB_1_IO_Subgroup
1089 {
1090     Iec104BsiType bsi;
1091     Iec104QdsType qds;
1092     Iec104Cp56Time2aType sevenOctetBinaryTime;
1093 }__attribute__((packed));
1094 
1095 struct Iec104M_BO_TB_1_IO_Group
1096 {
1097     Iec104InformationObjectAddressThreeOctetType ioa;
1098     Iec104M_BO_TB_1_IO_Subgroup subgroup;
1099 }__attribute__((packed));
1100 
1101 
1102 // ASDU Type M_ME_TD_1
1103 // Ident 34
1104 // Measured value, normalized value with time tag CP56Time2a
1105 
1106 struct Iec104M_ME_TD_1_IO_Subgroup
1107 {
1108     Iec104NvaType nva;
1109     Iec104QdsType qds;
1110     Iec104Cp56Time2aType sevenOctetBinaryTime;
1111 }__attribute__((packed));
1112 
1113 struct Iec104M_ME_TD_1_IO_Group
1114 {
1115     Iec104InformationObjectAddressThreeOctetType ioa;
1116     Iec104M_ME_TD_1_IO_Subgroup subgroup;
1117 }__attribute__((packed));
1118 
1119 
1120 // ASDU Type M_ME_TE_1
1121 // Ident 35
1122 // Measured value, scaled value with time tag CP56Time2a
1123 
1124 struct Iec104M_ME_TE_1_IO_Subgroup
1125 {
1126     Iec104SvaType sva;
1127     Iec104QdsType qds;
1128     Iec104Cp56Time2aType sevenOctetBinaryTime;
1129 }__attribute__((packed));
1130 
1131 struct Iec104M_ME_TE_1_IO_Group
1132 {
1133     Iec104InformationObjectAddressThreeOctetType ioa;
1134     Iec104M_ME_TE_1_IO_Subgroup subgroup;
1135 }__attribute__((packed));
1136 
1137 
1138 // ASDU Type M_ME_TF_1
1139 // Ident 36
1140 // Measured value, short floating point number with time tag CP56Time2a
1141 
1142 struct Iec104M_ME_TF_1_IO_Subgroup
1143 {
1144     Iec104IeeeStd754Type ieeeStd754;
1145     Iec104QdsType qds;
1146     Iec104Cp56Time2aType sevenOctetBinaryTime;
1147 }__attribute__((packed));
1148 
1149 struct Iec104M_ME_TF_1_IO_Group
1150 {
1151     Iec104InformationObjectAddressThreeOctetType ioa;
1152     Iec104M_ME_TF_1_IO_Subgroup subgroup;
1153 }__attribute__((packed));
1154 
1155 
1156 // ASDU Type M_IT_TB_1
1157 // Ident 37
1158 // Integrated totals with time tag CP56Time2a
1159 
1160 struct Iec104M_IT_TB_1_IO_Subgroup
1161 {
1162     Iec104BcrType bcr;
1163     Iec104Cp56Time2aType sevenOctetBinaryTime;
1164 }__attribute__((packed));
1165 
1166 struct Iec104M_IT_TB_1_IO_Group
1167 {
1168     Iec104InformationObjectAddressThreeOctetType ioa;
1169     Iec104M_IT_TB_1_IO_Subgroup subgroup;
1170 }__attribute__((packed));
1171 
1172 
1173 // ASDU Type M_EP_TD_1
1174 // Ident 38
1175 // Event of protection equipment with time tag CP56Time2a
1176 
1177 struct Iec104M_EP_TD_1_IO_Subgroup
1178 {
1179     Iec104SepType sep;
1180     Iec104Cp16Time2aType elapsedTime;
1181     Iec104Cp56Time2aType sevenOctetBinaryTime;
1182 }__attribute__((packed));
1183 
1184 struct Iec104M_EP_TD_1_IO_Group
1185 {
1186     Iec104InformationObjectAddressThreeOctetType ioa;
1187     Iec104M_EP_TD_1_IO_Subgroup subgroup;
1188 }__attribute__((packed));
1189 
1190 
1191 // ASDU Type M_EP_TE_1
1192 // Ident 39
1193 // Packed start events of protection equipment with time tag CP56Time2a
1194 
1195 struct Iec104M_EP_TE_1_IO_Subgroup
1196 {
1197     Iec104SepType sep;
1198     Iec104QdpType qdp;
1199     Iec104Cp16Time2aType relayDurationTime;
1200     Iec104Cp56Time2aType sevenOctetBinaryTime;
1201 }__attribute__((packed));
1202 
1203 struct Iec104M_EP_TE_1_IO_Group
1204 {
1205     Iec104InformationObjectAddressThreeOctetType ioa;
1206     Iec104M_EP_TE_1_IO_Subgroup subgroup;
1207 }__attribute__((packed));
1208 
1209 
1210 // ASDU Type M_EP_TF_1
1211 // Ident 40
1212 // Packed output circuit information of protection equipment with time tag CP56Time2a
1213 
1214 struct Iec104M_EP_TF_1_IO_Subgroup
1215 {
1216     Iec104OciType oci;
1217     Iec104QdpType qdp;
1218     Iec104Cp16Time2aType relayDurationTime;
1219     Iec104Cp56Time2aType sevenOctetBinaryTime;
1220 }__attribute__((packed));
1221 
1222 struct Iec104M_EP_TF_1_IO_Group
1223 {
1224     Iec104InformationObjectAddressThreeOctetType ioa;
1225     Iec104M_EP_TF_1_IO_Subgroup subgroup;
1226 }__attribute__((packed));
1227 
1228 
1229 
1230 //
1231 // ASDUs for process information in control direction
1232 //
1233 
1234 // ASDU Type C_SC_NA_1
1235 
1236 struct Iec104C_SC_NA_1_IO_Subgroup
1237 {
1238     Iec104ScoType sco;
1239 }__attribute__((packed));
1240 
1241 struct Iec104C_SC_NA_1_IO_Group
1242 {
1243     Iec104InformationObjectAddressThreeOctetType ioa;
1244     Iec104C_SC_NA_1_IO_Subgroup subgroup;
1245 }__attribute__((packed));
1246 
1247 
1248 // ASDU Type C_DC_NA_1
1249 
1250 struct Iec104C_DC_NA_1_IO_Subgroup
1251 {
1252     Iec104DcoType dco;
1253 }__attribute__((packed));
1254 
1255 struct Iec104C_DC_NA_1_IO_Group
1256 {
1257     Iec104InformationObjectAddressThreeOctetType ioa;
1258     Iec104C_DC_NA_1_IO_Subgroup subgroup;
1259 }__attribute__((packed));
1260 
1261 
1262 // ASDU Type C_RC_NA_1
1263 
1264 struct Iec104C_RC_NA_1_IO_Subgroup
1265 {
1266     Iec104RcoType rco;
1267 }__attribute__((packed));
1268 
1269 struct Iec104C_RC_NA_1_IO_Group
1270 {
1271     Iec104InformationObjectAddressThreeOctetType ioa;
1272     Iec104C_RC_NA_1_IO_Subgroup subgroup;
1273 }__attribute__((packed));
1274 
1275 
1276 // ASDU Type C_SE_NA_1
1277 
1278 struct Iec104C_SE_NA_1_IO_Subgroup
1279 {
1280     Iec104NvaType nva;
1281     Iec104QosType qos;
1282 }__attribute__((packed));
1283 
1284 struct Iec104C_SE_NA_1_IO_Group
1285 {
1286     Iec104InformationObjectAddressThreeOctetType ioa;
1287     Iec104C_SE_NA_1_IO_Subgroup subgroup;
1288 }__attribute__((packed));
1289 
1290 
1291 // ASDU Type C_SE_NB_1
1292 
1293 struct Iec104C_SE_NB_1_IO_Subgroup
1294 {
1295     Iec104SvaType sva;
1296     Iec104QosType qos;
1297 }__attribute__((packed));
1298 
1299 struct Iec104C_SE_NB_1_IO_Group
1300 {
1301     Iec104InformationObjectAddressThreeOctetType ioa;
1302     Iec104C_SE_NB_1_IO_Subgroup subgroup;
1303 }__attribute__((packed));
1304 
1305 
1306 // ASDU Type C_SE_NC_1
1307 
1308 struct Iec104C_SE_NC_1_IO_Subgroup
1309 {
1310     Iec104IeeeStd754Type ieeeStd754;
1311     Iec104QosType qos;
1312 }__attribute__((packed));
1313 
1314 struct Iec104C_SE_NC_1_IO_Group
1315 {
1316     Iec104InformationObjectAddressThreeOctetType ioa;
1317     Iec104C_SE_NC_1_IO_Subgroup subgroup;
1318 }__attribute__((packed));
1319 
1320 
1321 // ASDU Type C_BO_NA_1
1322 
1323 struct Iec104C_BO_NA_1_IO_Subgroup
1324 {
1325     Iec104BsiType bsi;
1326 }__attribute__((packed));
1327 
1328 struct Iec104C_BO_NA_1_IO_Group
1329 {
1330     Iec104InformationObjectAddressThreeOctetType ioa;
1331     Iec104C_BO_NA_1_IO_Subgroup subgroup;
1332 }__attribute__((packed));
1333 
1334 
1335 // ASDU Type C_SC_TA_1
1336 // Ident 58
1337 // Single command with time tag CP56Time2a
1338 //   IEC-60870-5-104
1339 
1340 struct Iec104C_SC_TA_1_IO_Subgroup
1341 {
1342     Iec104ScoType sco;
1343     Iec104Cp56Time2aType sevenOctetBinaryTime;
1344 }__attribute__((packed));
1345 
1346 struct Iec104C_SC_TA_1_IO_Group
1347 {
1348     Iec104InformationObjectAddressThreeOctetType ioa;
1349     Iec104C_SC_TA_1_IO_Subgroup subgroup;
1350 }__attribute__((packed));
1351 
1352 
1353 // ASDU Type C_DC_TA_1
1354 // Ident 59
1355 // Double command with time tag CP56Time2a
1356 //   IEC-60870-5-104
1357 
1358 struct Iec104C_DC_TA_1_IO_Subgroup
1359 {
1360     Iec104DcoType dco;
1361     Iec104Cp56Time2aType sevenOctetBinaryTime;
1362 }__attribute__((packed));
1363 
1364 struct Iec104C_DC_TA_1_IO_Group
1365 {
1366     Iec104InformationObjectAddressThreeOctetType ioa;
1367     Iec104C_DC_TA_1_IO_Subgroup subgroup;
1368 }__attribute__((packed));
1369 
1370 
1371 // ASDU Type C_RC_TA_1
1372 // Ident 60
1373 // Regulating step command with time tag CP56Time2a
1374 //   IEC-60870-5-104
1375 
1376 struct Iec104C_RC_TA_1_IO_Subgroup
1377 {
1378     Iec104RcoType rco;
1379     Iec104Cp56Time2aType sevenOctetBinaryTime;
1380 }__attribute__((packed));
1381 
1382 struct Iec104C_RC_TA_1_IO_Group
1383 {
1384     Iec104InformationObjectAddressThreeOctetType ioa;
1385     Iec104C_RC_TA_1_IO_Subgroup subgroup;
1386 }__attribute__((packed));
1387 
1388 
1389 // ASDU Type C_SE_TA_1
1390 // Ident 61
1391 // Set-point command with time tag CP56Time2a, normalized value
1392 //   IEC-60870-5-104
1393 
1394 struct Iec104C_SE_TA_1_IO_Subgroup
1395 {
1396     Iec104NvaType nva;
1397     Iec104QosType qos;
1398     Iec104Cp56Time2aType sevenOctetBinaryTime;
1399 }__attribute__((packed));
1400 
1401 struct Iec104C_SE_TA_1_IO_Group
1402 {
1403     Iec104InformationObjectAddressThreeOctetType ioa;
1404     Iec104C_SE_TA_1_IO_Subgroup subgroup;
1405 }__attribute__((packed));
1406 
1407 
1408 // ASDU Type C_SE_TB_1
1409 // Ident 62
1410 // Set-point command with time tag CP56Time2a, scaled value
1411 //   IEC-60870-5-104
1412 
1413 struct Iec104C_SE_TB_1_IO_Subgroup
1414 {
1415     Iec104SvaType sva;
1416     Iec104QosType qos;
1417     Iec104Cp56Time2aType sevenOctetBinaryTime;
1418 }__attribute__((packed));
1419 
1420 struct Iec104C_SE_TB_1_IO_Group
1421 {
1422     Iec104InformationObjectAddressThreeOctetType ioa;
1423     Iec104C_SE_TB_1_IO_Subgroup subgroup;
1424 }__attribute__((packed));
1425 
1426 
1427 // ASDU Type C_SE_TC_1
1428 // Ident 63
1429 // Set-point command with time tag CP56Time2a, short floating point number
1430 //   IEC-60870-5-104
1431 
1432 struct Iec104C_SE_TC_1_IO_Subgroup
1433 {
1434     Iec104IeeeStd754Type ieeeStd754;
1435     Iec104QosType qos;
1436     Iec104Cp56Time2aType sevenOctetBinaryTime;
1437 }__attribute__((packed));
1438 
1439 struct Iec104C_SE_TC_1_IO_Group
1440 {
1441     Iec104InformationObjectAddressThreeOctetType ioa;
1442     Iec104C_SE_TC_1_IO_Subgroup subgroup;
1443 }__attribute__((packed));
1444 
1445 
1446 // ASDU Type C_BO_TA_1
1447 // Ident 64
1448 // Bitstring of 32 bit with time tag CP56Time2a
1449 //   IEC-60870-5-104
1450 
1451 struct Iec104C_BO_TA_1_IO_Subgroup
1452 {
1453     Iec104BsiType bsi;
1454     Iec104Cp56Time2aType sevenOctetBinaryTime;
1455 }__attribute__((packed));
1456 
1457 struct Iec104C_BO_TA_1_IO_Group
1458 {
1459     Iec104InformationObjectAddressThreeOctetType ioa;
1460     Iec104C_BO_TA_1_IO_Subgroup subgroup;
1461 }__attribute__((packed));
1462 
1463 
1464 
1465 //
1466 // ASDUs for system information in monitor direction
1467 //
1468 
1469 // ASDU Type M_EI_NA_1
1470 // Ident 70
1471 // End of initialization
1472 
1473 struct Iec104M_EI_NA_1_IO_Subgroup
1474 {
1475     Iec104CoiType coi;
1476 }__attribute__((packed));
1477 
1478 struct Iec104M_EI_NA_1_IO_Group
1479 {
1480     Iec104InformationObjectAddressThreeOctetType ioa;
1481     Iec104M_EI_NA_1_IO_Subgroup subgroup;
1482 }__attribute__((packed));
1483 
1484 
1485 
1486 //
1487 // ASDUs for system information in control direction
1488 //
1489 
1490 // ASDU Type C_IC_NA_1
1491 // Ident 100
1492 // Interrogation command
1493 
1494 struct Iec104C_IC_NA_1_IO_Subgroup
1495 {
1496     Iec104QoiType qoi;
1497 }__attribute__((packed));
1498 
1499 struct Iec104C_IC_NA_1_IO_Group
1500 {
1501     Iec104InformationObjectAddressThreeOctetType ioa;
1502     Iec104C_IC_NA_1_IO_Subgroup subgroup;
1503 }__attribute__((packed));
1504 
1505 
1506 // ASDU Type C_CI_NA_1
1507 // Ident 101
1508 // Counter interrogation command
1509 
1510 struct Iec104C_CI_NA_1_IO_Subgroup
1511 {
1512     Iec104QccType qcc;
1513 }__attribute__((packed));
1514 
1515 struct Iec104C_CI_NA_1_IO_Group
1516 {
1517     Iec104InformationObjectAddressThreeOctetType ioa;
1518     Iec104C_CI_NA_1_IO_Subgroup subgroup;
1519 }__attribute__((packed));
1520 
1521 
1522 // ASDU Type C_RD_NA_1
1523 // Ident 102
1524 // Read command
1525 
1526 struct Iec104C_RD_NA_1_IO_Subgroup
1527 {
1528     // No subgroup for this type
1529 }__attribute__((packed));
1530 
1531 struct Iec104C_RD_NA_1_IO_Group
1532 {
1533     Iec104InformationObjectAddressThreeOctetType ioa;
1534     Iec104C_RD_NA_1_IO_Subgroup subgroup;
1535 }__attribute__((packed));
1536 
1537 
1538 // ASDU Type C_CS_NA_1
1539 // Ident 103
1540 // Clock synchronization command
1541 
1542 struct Iec104C_CS_NA_1_IO_Subgroup
1543 {
1544     Iec104Cp56Time2aType sevenOctetBinaryTime;
1545 }__attribute__((packed));
1546 
1547 struct Iec104C_CS_NA_1_IO_Group
1548 {
1549     Iec104InformationObjectAddressThreeOctetType ioa;
1550     Iec104C_CS_NA_1_IO_Subgroup subgroup;
1551 }__attribute__((packed));
1552 
1553 
1554 // ASDU Type C_TS_NA_1
1555 // Ident 104
1556 // Test command
1557 
1558 struct Iec104C_TS_NA_1_IO_Subgroup
1559 {
1560     Iec104FbpType fbp;
1561 }__attribute__((packed));
1562 
1563 struct Iec104C_TS_NA_1_IO_Group
1564 {
1565     Iec104InformationObjectAddressThreeOctetType ioa;
1566     Iec104C_TS_NA_1_IO_Subgroup subgroup;
1567 }__attribute__((packed));
1568 
1569 
1570 // ASDU Type C_RP_NA_1
1571 // Ident 105
1572 // Reset process command
1573 
1574 struct Iec104C_RP_NA_1_IO_Subgroup
1575 {
1576     Iec104QrpType qrp;
1577 }__attribute__((packed));
1578 
1579 struct Iec104C_RP_NA_1_IO_Group
1580 {
1581     Iec104InformationObjectAddressThreeOctetType ioa;
1582     Iec104C_RP_NA_1_IO_Subgroup subgroup;
1583 }__attribute__((packed));
1584 
1585 
1586 // ASDU Type C_CD_NA_1
1587 // Ident 106
1588 // Delay acquisition command
1589 
1590 struct Iec104C_CD_NA_1_IO_Subgroup
1591 {
1592     Iec104Cp16Time2aType msUpToSeconds;
1593 }__attribute__((packed));
1594 
1595 struct Iec104C_CD_NA_1_IO_Group
1596 {
1597     Iec104InformationObjectAddressThreeOctetType ioa;
1598     Iec104C_CD_NA_1_IO_Subgroup subgroup;
1599 }__attribute__((packed));
1600 
1601 
1602 // ASDU Type C_TS_TA_1
1603 // Ident 107
1604 // Test command with time tag CP56Time2a
1605 //   IEC-60870-5-104
1606 
1607 struct Iec104C_TS_TA_1_IO_Subgroup
1608 {
1609     Iec104TscType tsc;
1610     Iec104Cp56Time2aType sevenOctetBinaryTime;
1611 }__attribute__((packed));
1612 
1613 struct Iec104C_TS_TA_1_IO_Group
1614 {
1615     Iec104InformationObjectAddressThreeOctetType ioa;
1616     Iec104C_TS_TA_1_IO_Subgroup subgroup;
1617 }__attribute__((packed));
1618 
1619 
1620 
1621 //
1622 // ASDUs for parameter in control direction
1623 //
1624 
1625 // ASDU Type P_ME_NA_1
1626 // Ident 110
1627 // Parameter of measured values, normalized value
1628 
1629 struct Iec104P_ME_NA_1_IO_Subgroup
1630 {
1631     Iec104NvaType nva;
1632     Iec104QpmType qpm;
1633 }__attribute__((packed));
1634 
1635 struct Iec104P_ME_NA_1_IO_Group
1636 {
1637     Iec104InformationObjectAddressThreeOctetType ioa;
1638     Iec104P_ME_NA_1_IO_Subgroup subgroup;
1639 }__attribute__((packed));
1640 
1641 
1642 // ASDU Type P_ME_NB_1
1643 // Ident 111
1644 // Parameter of measured values, scaled value
1645 
1646 struct Iec104P_ME_NB_1_IO_Subgroup
1647 {
1648     Iec104SvaType sva;
1649     Iec104QpmType qpm;
1650 }__attribute__((packed));
1651 
1652 struct Iec104P_ME_NB_1_IO_Group
1653 {
1654     Iec104InformationObjectAddressThreeOctetType ioa;
1655     Iec104P_ME_NB_1_IO_Subgroup subgroup;
1656 }__attribute__((packed));
1657 
1658 
1659 // ASDU Type P_ME_NC_1
1660 // Ident 112
1661 // Parameter of measured values, short floating point number
1662 
1663 struct Iec104P_ME_NC_1_IO_Subgroup
1664 {
1665     Iec104IeeeStd754Type ieeeStd754;
1666     Iec104QpmType qpm;
1667 }__attribute__((packed));
1668 
1669 struct Iec104P_ME_NC_1_IO_Group
1670 {
1671     Iec104InformationObjectAddressThreeOctetType ioa;
1672     Iec104P_ME_NC_1_IO_Subgroup subgroup;
1673 }__attribute__((packed));
1674 
1675 
1676 // ASDU Type P_AC_NA_1
1677 // Ident 113
1678 // Parameter activation
1679 
1680 struct Iec104P_AC_NA_1_IO_Subgroup
1681 {
1682     Iec104QpaType qpa;
1683 }__attribute__((packed));
1684 
1685 struct Iec104P_AC_NA_1_IO_Group
1686 {
1687     Iec104InformationObjectAddressThreeOctetType ioa;
1688     Iec104P_AC_NA_1_IO_Subgroup subgroup;
1689 }__attribute__((packed));
1690 
1691 
1692 
1693 //
1694 // ASDUs for file transfer
1695 //
1696 
1697 // ASDU Type F_FR_NA_1
1698 // Ident 120
1699 // File ready
1700 
1701 struct Iec104F_FR_NA_1_IO_Subgroup
1702 {
1703     Iec104NofType nameOfFile;
1704     Iec104LofType lengthOfFile;
1705     Iec104FrqType frq;
1706 }__attribute__((packed));
1707 
1708 struct Iec104F_FR_NA_1_IO_Group
1709 {
1710     Iec104InformationObjectAddressThreeOctetType ioa;
1711     Iec104F_FR_NA_1_IO_Subgroup subgroup;
1712 }__attribute__((packed));
1713 
1714 
1715 // ASDU Type F_SR_NA_1
1716 // Ident 121
1717 // Section ready
1718 
1719 struct Iec104F_SR_NA_1_IO_Subgroup
1720 {
1721     Iec104NofType nameOfFile;
1722     Iec104NosType nameOfSection;
1723     Iec104LofType lengthOfFileOrSection;
1724     Iec104SrqType srq;
1725 }__attribute__((packed));
1726 
1727 struct Iec104F_SR_NA_1_IO_Group
1728 {
1729     Iec104InformationObjectAddressThreeOctetType ioa;
1730     Iec104F_SR_NA_1_IO_Subgroup subgroup;
1731 }__attribute__((packed));
1732 
1733 
1734 // ASDU Type F_SC_NA_1
1735 // Ident 122
1736 // Call directory, select file, call file, call section
1737 
1738 struct Iec104F_SC_NA_1_IO_Subgroup
1739 {
1740     Iec104NofType nameOfFile;
1741     Iec104NosType nameOfSection;
1742     Iec104ScqType scq;
1743 }__attribute__((packed));
1744 
1745 struct Iec104F_SC_NA_1_IO_Group
1746 {
1747     Iec104InformationObjectAddressThreeOctetType ioa;
1748     Iec104F_SC_NA_1_IO_Subgroup subgroup;
1749 }__attribute__((packed));
1750 
1751 
1752 // ASDU Type F_LS_NA_1
1753 // Ident 123
1754 // Last section, last segment
1755 
1756 struct Iec104F_LS_NA_1_IO_Subgroup
1757 {
1758     Iec104NofType nameOfFile;
1759     Iec104NosType nameOfSection;
1760     Iec104LsqType lsq;
1761     Iec104ChsType chs;
1762 }__attribute__((packed));
1763 
1764 struct Iec104F_LS_NA_1_IO_Group
1765 {
1766     Iec104InformationObjectAddressThreeOctetType ioa;
1767     Iec104F_LS_NA_1_IO_Subgroup subgroup;
1768 }__attribute__((packed));
1769 
1770 
1771 // ASDU Type F_AF_NA_1
1772 // Ident 124
1773 // ACK file, ACK section
1774 
1775 struct Iec104F_AF_NA_1_IO_Subgroup
1776 {
1777     Iec104NofType nameOfFile;
1778     Iec104NosType nameOfSection;
1779     Iec104AfqType afq;
1780 }__attribute__((packed));
1781 
1782 struct Iec104F_AF_NA_1_IO_Group
1783 {
1784     Iec104InformationObjectAddressThreeOctetType ioa;
1785     Iec104F_AF_NA_1_IO_Subgroup subgroup;
1786 }__attribute__((packed));
1787 
1788 
1789 // ASDU Type F_SG_NA_1
1790 // Ident 125
1791 // Single information object
1792 
1793 struct Iec104F_SG_NA_1_IO_Subgroup
1794 {
1795     Iec104NofType nameOfFile;
1796     Iec104NosType nameOfSection;
1797     Iec104LosType lengthOfSegment;
1798     Iec104SegmentType segment;
1799 }__attribute__((packed));
1800 
1801 struct Iec104F_SG_NA_1_IO_Group
1802 {
1803     Iec104InformationObjectAddressThreeOctetType ioa;
1804     Iec104F_SG_NA_1_IO_Subgroup subgroup;
1805 }__attribute__((packed));
1806 
1807 
1808 // ASDU Type F_DR_TA_1
1809 // Ident 126
1810 // Sequence of information elements in a single information object
1811 
1812 struct Iec104F_DR_TA_1_IO_Subgroup
1813 {
1814     Iec104NofType nameOfFileOrSubdirectory;
1815     Iec104LofType lengthOfFile;
1816     Iec104SofType sof;
1817     Iec104Cp56Time2aType creationTimeOfFile;
1818 }__attribute__((packed));
1819 
1820 struct Iec104F_DR_TA_1_IO_Group
1821 {
1822     Iec104InformationObjectAddressThreeOctetType ioa;
1823     Iec104F_DR_TA_1_IO_Subgroup subgroup;
1824 }__attribute__((packed));
1825 
1826 
1827 // ASDU Type F_SC_NB_1
1828 // Ident 127
1829 // QueryLog – Request archive file
1830 
1831 struct Iec104F_SC_NB_1_IO_Subgroup
1832 {
1833     Iec104NofType nameOfFile;
1834     Iec104Cp56Time2aType startTime;
1835     Iec104Cp56Time2aType stopTime;
1836 }__attribute__((packed));
1837 
1838 struct Iec104F_SC_NB_1_IO_Group
1839 {
1840     Iec104InformationObjectAddressThreeOctetType ioa;
1841     Iec104F_SC_NB_1_IO_Subgroup subgroup;
1842 }__attribute__((packed));
1843 
1844 
1845 //
1846 // Generic ASDU
1847 //
1848 
1849 struct Iec104GenericAsdu
1850 {
1851     uint8_t typeId;
1852     Iec104VariableStructureQualifierType variableStructureQualifier;
1853     Iec104CauseOfTransmissionType causeOfTransmission;
1854     Iec104CommonAddressOfAsduType commonAddressOfAsdu;
1855     union
1856     {
1857         Iec104M_SP_NA_1_IO_Group m_sp_na_1;
1858         Iec104M_SP_TA_1_IO_Group m_sp_ta_1;
1859         Iec104M_DP_NA_1_IO_Group m_dp_na_1;
1860         Iec104M_DP_TA_1_IO_Group m_dp_ta_1;
1861         Iec104M_ST_NA_1_IO_Group m_st_na_1;
1862         Iec104M_ST_TA_1_IO_Group m_st_ta_1;
1863         Iec104M_BO_NA_1_IO_Group m_bo_na_1;
1864         Iec104M_BO_TA_1_IO_Group m_bo_ta_1;
1865         Iec104M_ME_NA_1_IO_Group m_me_na_1;
1866         Iec104M_ME_TA_1_IO_Group m_me_ta_1;
1867         Iec104M_ME_NB_1_IO_Group m_me_nb_1;
1868         Iec104M_ME_TB_1_IO_Group m_me_tb_1;
1869         Iec104M_ME_NC_1_IO_Group m_me_nc_1;
1870         Iec104M_ME_TC_1_IO_Group m_me_tc_1;
1871         Iec104M_IT_NA_1_IO_Group m_it_na_1;
1872         Iec104M_IT_TA_1_IO_Group m_it_ta_1;
1873         Iec104M_EP_TA_1_IO_Group m_ep_ta_1;
1874         Iec104M_EP_TB_1_IO_Group m_ep_tb_1;
1875         Iec104M_EP_TC_1_IO_Group m_ep_tc_1;
1876         Iec104M_PS_NA_1_IO_Group m_ps_na_1;
1877         Iec104M_ME_ND_1_IO_Group m_me_nd_1;
1878         Iec104M_SP_TB_1_IO_Group m_sp_tb_1;
1879         Iec104M_DP_TB_1_IO_Group m_dp_tb_1;
1880         Iec104M_ST_TB_1_IO_Group m_st_tb_1;
1881         Iec104M_BO_TB_1_IO_Group m_bo_tb_1;
1882         Iec104M_ME_TD_1_IO_Group m_me_td_1;
1883         Iec104M_ME_TE_1_IO_Group m_me_te_1;
1884         Iec104M_ME_TF_1_IO_Group m_me_tf_1;
1885         Iec104M_IT_TB_1_IO_Group m_it_tb_1;
1886         Iec104M_EP_TD_1_IO_Group m_ep_td_1;
1887         Iec104M_EP_TE_1_IO_Group m_ep_te_1;
1888         Iec104M_EP_TF_1_IO_Group m_ep_tf_1;
1889         Iec104C_SC_NA_1_IO_Group c_sc_na_1;
1890         Iec104C_DC_NA_1_IO_Group c_dc_na_1;
1891         Iec104C_RC_NA_1_IO_Group c_rc_na_1;
1892         Iec104C_SE_NA_1_IO_Group c_se_na_1;
1893         Iec104C_SE_NB_1_IO_Group c_se_nb_1;
1894         Iec104C_SE_NC_1_IO_Group c_se_nc_1;
1895         Iec104C_BO_NA_1_IO_Group c_bo_na_1;
1896         Iec104C_SC_TA_1_IO_Group c_sc_ta_1;
1897         Iec104C_DC_TA_1_IO_Group c_dc_ta_1;
1898         Iec104C_RC_TA_1_IO_Group c_rc_ta_1;
1899         Iec104C_SE_TA_1_IO_Group c_se_ta_1;
1900         Iec104C_SE_TB_1_IO_Group c_se_tb_1;
1901         Iec104C_SE_TC_1_IO_Group c_se_tc_1;
1902         Iec104C_BO_TA_1_IO_Group c_bo_ta_1;
1903         Iec104M_EI_NA_1_IO_Group m_ei_na_1;
1904         Iec104C_IC_NA_1_IO_Group c_ic_na_1;
1905         Iec104C_CI_NA_1_IO_Group c_ci_na_1;
1906         Iec104C_RD_NA_1_IO_Group c_rd_na_1;
1907         Iec104C_CS_NA_1_IO_Group c_cs_na_1;
1908         Iec104C_TS_NA_1_IO_Group c_ts_na_1;
1909         Iec104C_RP_NA_1_IO_Group c_rp_na_1;
1910         Iec104C_CD_NA_1_IO_Group c_cd_na_1;
1911         Iec104C_TS_TA_1_IO_Group c_ts_ta_1;
1912         Iec104P_ME_NA_1_IO_Group p_me_na_1;
1913         Iec104P_ME_NB_1_IO_Group p_me_nb_1;
1914         Iec104P_ME_NC_1_IO_Group p_me_nc_1;
1915         Iec104P_AC_NA_1_IO_Group p_ac_na_1;
1916         Iec104F_FR_NA_1_IO_Group f_fr_na_1;
1917         Iec104F_SR_NA_1_IO_Group f_sr_na_1;
1918         Iec104F_SC_NA_1_IO_Group f_sc_na_1;
1919         Iec104F_LS_NA_1_IO_Group f_ls_na_1;
1920         Iec104F_AF_NA_1_IO_Group f_af_na_1;
1921         Iec104F_SG_NA_1_IO_Group f_sg_na_1;
1922         Iec104F_DR_TA_1_IO_Group f_dr_ta_1;
1923         Iec104F_SC_NB_1_IO_Group f_sc_nb_1;
1924     };
1925 }__attribute__((packed));
1926 
1927 
1928 //
1929 // APCI structs
1930 //
1931 
1932 // Header fields common to every APCI
1933 struct Iec104Header
1934 {
1935     uint8_t start;
1936     uint8_t length;
1937 }__attribute__((packed));
1938 
1939 // APCI Type U
1940 struct Iec104ApciU
1941 {
1942     Iec104Header header;
1943     uint8_t apciTypeMajor : 1;
1944     uint8_t apciTypeMinor : 1;
1945     uint8_t startdtAct : 1;
1946     uint8_t startdtCon : 1;
1947     uint8_t stopdtAct : 1;
1948     uint8_t stopdtCon : 1;
1949     uint8_t testfrAct : 1;
1950     uint8_t testfrCon : 1;
1951     uint8_t reserved1;
1952     uint16_t reserved2 : 1;
1953     uint16_t reserved3 : 15;
1954 }__attribute__((packed));
1955 
1956 // APCI Type S
1957 struct Iec104ApciS
1958 {
1959     Iec104Header header;
1960     uint16_t apciTypeMajor : 1;
1961     uint16_t apciTypeMinor : 1;
1962     uint16_t reserved1 : 14;
1963     uint16_t reserved2 : 1;
1964     uint16_t recvSeq : 15;
1965 }__attribute__((packed));
1966 
1967 // APCI Type I
1968 struct Iec104ApciI
1969 {
1970     Iec104Header header;
1971     uint16_t apciTypeMajor : 1;
1972     uint16_t sendSeq : 15;
1973     uint16_t reserved : 1;
1974     uint16_t recvSeq : 15;
1975     Iec104GenericAsdu asdu;
1976 }__attribute__((packed));
1977 
1978 // structs used to determine if there is an issue with the passed ASDU
1979 struct Iec104AsduCheckCauseOfTx
1980 {
1981     uint64_t percyc : 1;
1982     uint64_t back : 1;
1983     uint64_t spont : 1;
1984     uint64_t init : 1;
1985     uint64_t req : 1;
1986     uint64_t act : 1;
1987     uint64_t actcon : 1;
1988     uint64_t deact : 1;
1989     uint64_t deactcon : 1;
1990     uint64_t actterm : 1;
1991     uint64_t retrem : 1;
1992     uint64_t retloc : 1;
1993     uint64_t file : 1;
1994     uint64_t inrogen : 1;
1995     uint64_t inro1 : 1;
1996     uint64_t inro2 : 1;
1997     uint64_t inro3 : 1;
1998     uint64_t inro4 : 1;
1999     uint64_t inro5 : 1;
2000     uint64_t inro6 : 1;
2001     uint64_t inro7 : 1;
2002     uint64_t inro8 : 1;
2003     uint64_t inro9 : 1;
2004     uint64_t inro10 : 1;
2005     uint64_t inro11 : 1;
2006     uint64_t inro12 : 1;
2007     uint64_t inro13 : 1;
2008     uint64_t inro14 : 1;
2009     uint64_t inro15 : 1;
2010     uint64_t inro16 : 1;
2011     uint64_t reqcogen : 1;
2012     uint64_t reqco1 : 1;
2013     uint64_t reqco2 : 1;
2014     uint64_t reqco3 : 1;
2015     uint64_t reqco4 : 1;
2016     uint64_t unk_type_id : 1;
2017     uint64_t unk_cause_tx : 1;
2018     uint64_t unk_common_addr : 1;
2019     uint64_t unk_info_addr : 1;
2020 };
2021 
2022 struct Iec104AsduCheck
2023 {
2024     const Iec104ApciI* apci;
2025     bool sq0Allowed;
2026     bool sq1Allowed;
2027     bool multipleIOAllowed;
2028     Iec104AsduCheckCauseOfTx checkCauseOfTx;
2029 };
2030 
2031 #endif
2032 
2033