An mbed implementation of IEC 61850-9-2LE Sample Values. Creating using the rapid61850 library, available at: https://github.com/stevenblair/rapid61850.

Dependencies:   mbed

An mbed implementation of IEC 61850-9-2LE Sample Values. Creating using the rapid61850 library, available at: https://github.com/stevenblair/rapid61850.

Committer:
sblair
Date:
Tue Oct 02 21:31:05 2012 +0000
Revision:
0:f09b7bb8bcce
converted library to folder

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sblair 0:f09b7bb8bcce 1 /**
sblair 0:f09b7bb8bcce 2 * Rapid-prototyping protection schemes with IEC 61850
sblair 0:f09b7bb8bcce 3 *
sblair 0:f09b7bb8bcce 4 * Copyright (c) 2012 Steven Blair
sblair 0:f09b7bb8bcce 5 *
sblair 0:f09b7bb8bcce 6 * This program is free software; you can redistribute it and/or
sblair 0:f09b7bb8bcce 7 * modify it under the terms of the GNU General Public License
sblair 0:f09b7bb8bcce 8 * as published by the Free Software Foundation; either version 2
sblair 0:f09b7bb8bcce 9 * of the License, or (at your option) any later version.
sblair 0:f09b7bb8bcce 10
sblair 0:f09b7bb8bcce 11 * This program is distributed in the hope that it will be useful,
sblair 0:f09b7bb8bcce 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sblair 0:f09b7bb8bcce 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
sblair 0:f09b7bb8bcce 14 * GNU General Public License for more details.
sblair 0:f09b7bb8bcce 15
sblair 0:f09b7bb8bcce 16 * You should have received a copy of the GNU General Public License
sblair 0:f09b7bb8bcce 17 * along with this program; if not, write to the Free Software
sblair 0:f09b7bb8bcce 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
sblair 0:f09b7bb8bcce 19 */
sblair 0:f09b7bb8bcce 20
sblair 0:f09b7bb8bcce 21 #include "ctypes.h"
sblair 0:f09b7bb8bcce 22 #include "datatypes.h"
sblair 0:f09b7bb8bcce 23 #include "ied.h"
sblair 0:f09b7bb8bcce 24 #include "gseDecodeBasic.h"
sblair 0:f09b7bb8bcce 25 #include <string.h>
sblair 0:f09b7bb8bcce 26
sblair 0:f09b7bb8bcce 27 // GSE decoding of basic types
sblair 0:f09b7bb8bcce 28 int BER_DECODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
sblair 0:f09b7bb8bcce 29 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 30 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 31
sblair 0:f09b7bb8bcce 32 if (buf[offset++] == 0x87) {
sblair 0:f09b7bb8bcce 33 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 34 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 35
sblair 0:f09b7bb8bcce 36 // check for fixed-length GOOSE. If not, check for 8 bits for exponent
sblair 0:f09b7bb8bcce 37 if (len == 5 && buf[offset] == 0x08) {
sblair 0:f09b7bb8bcce 38 netmemcpy(value, &buf[offset + 1], len - 1);
sblair 0:f09b7bb8bcce 39 }
sblair 0:f09b7bb8bcce 40 else if (len == 4) {
sblair 0:f09b7bb8bcce 41 netmemcpy(value, &buf[offset], len);
sblair 0:f09b7bb8bcce 42 }
sblair 0:f09b7bb8bcce 43 }
sblair 0:f09b7bb8bcce 44
sblair 0:f09b7bb8bcce 45 return offset + len;
sblair 0:f09b7bb8bcce 46 }
sblair 0:f09b7bb8bcce 47
sblair 0:f09b7bb8bcce 48 int BER_DECODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
sblair 0:f09b7bb8bcce 49 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 50 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 51
sblair 0:f09b7bb8bcce 52 if (buf[offset++] == 0x87) {
sblair 0:f09b7bb8bcce 53 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 54 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 55
sblair 0:f09b7bb8bcce 56 // check for fixed-length GOOSE. If not, check for 11 bits for exponent
sblair 0:f09b7bb8bcce 57 if (len == 9 && buf[offset] == 0x0B) {
sblair 0:f09b7bb8bcce 58 netmemcpy(value, &buf[offset + 1], len - 1);
sblair 0:f09b7bb8bcce 59 }
sblair 0:f09b7bb8bcce 60 else if (len == 8) {
sblair 0:f09b7bb8bcce 61 netmemcpy(value, &buf[offset], len);
sblair 0:f09b7bb8bcce 62 }
sblair 0:f09b7bb8bcce 63 }
sblair 0:f09b7bb8bcce 64
sblair 0:f09b7bb8bcce 65 return offset + len;
sblair 0:f09b7bb8bcce 66 }
sblair 0:f09b7bb8bcce 67 int BER_DECODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
sblair 0:f09b7bb8bcce 68 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 69 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 70
sblair 0:f09b7bb8bcce 71 if (buf[offset] == ASN1_TAG_BIT_STRING) {
sblair 0:f09b7bb8bcce 72 offset++;
sblair 0:f09b7bb8bcce 73 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 74 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 75
sblair 0:f09b7bb8bcce 76 netmemcpy(value, &buf[offset + 1], len - 1); // skip over one byte (which contains number of unused bits)
sblair 0:f09b7bb8bcce 77 }
sblair 0:f09b7bb8bcce 78
sblair 0:f09b7bb8bcce 79 return offset + len;
sblair 0:f09b7bb8bcce 80 }
sblair 0:f09b7bb8bcce 81 int BER_DECODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
sblair 0:f09b7bb8bcce 82 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 83 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 84
sblair 0:f09b7bb8bcce 85 if (buf[offset++] == 0x89) {
sblair 0:f09b7bb8bcce 86 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 87 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 88
sblair 0:f09b7bb8bcce 89 netmemcpy(value, &buf[offset], len);
sblair 0:f09b7bb8bcce 90 }
sblair 0:f09b7bb8bcce 91
sblair 0:f09b7bb8bcce 92 return offset + len;
sblair 0:f09b7bb8bcce 93 }
sblair 0:f09b7bb8bcce 94 int BER_DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) { // assuming enum is an int - allows any enum type to be used
sblair 0:f09b7bb8bcce 95 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 96 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 97
sblair 0:f09b7bb8bcce 98 if (buf[offset++] == ASN1_TAG_UNSIGNED) {
sblair 0:f09b7bb8bcce 99 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 100 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 101
sblair 0:f09b7bb8bcce 102 #if GOOSE_FIXED_SIZE == 1
sblair 0:f09b7bb8bcce 103 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT8);
sblair 0:f09b7bb8bcce 104 #else
sblair 0:f09b7bb8bcce 105 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
sblair 0:f09b7bb8bcce 106 #endif
sblair 0:f09b7bb8bcce 107 }
sblair 0:f09b7bb8bcce 108
sblair 0:f09b7bb8bcce 109 return offset + len;
sblair 0:f09b7bb8bcce 110 }
sblair 0:f09b7bb8bcce 111 int BER_DECODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) {
sblair 0:f09b7bb8bcce 112 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 113 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 114
sblair 0:f09b7bb8bcce 115 if (buf[offset++] == ASN1_TAG_INTEGER) {
sblair 0:f09b7bb8bcce 116 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 117 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 118
sblair 0:f09b7bb8bcce 119 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT8);
sblair 0:f09b7bb8bcce 120 }
sblair 0:f09b7bb8bcce 121
sblair 0:f09b7bb8bcce 122 return offset + len;
sblair 0:f09b7bb8bcce 123 }
sblair 0:f09b7bb8bcce 124 int BER_DECODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
sblair 0:f09b7bb8bcce 125 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 126 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 127
sblair 0:f09b7bb8bcce 128 if (buf[offset++] == ASN1_TAG_INTEGER) {
sblair 0:f09b7bb8bcce 129 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 130 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 131
sblair 0:f09b7bb8bcce 132 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT16);
sblair 0:f09b7bb8bcce 133 }
sblair 0:f09b7bb8bcce 134
sblair 0:f09b7bb8bcce 135 return offset + len;
sblair 0:f09b7bb8bcce 136 }
sblair 0:f09b7bb8bcce 137 int BER_DECODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
sblair 0:f09b7bb8bcce 138 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 139 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 140
sblair 0:f09b7bb8bcce 141 if (buf[offset++] == ASN1_TAG_INTEGER) {
sblair 0:f09b7bb8bcce 142 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 143 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 144
sblair 0:f09b7bb8bcce 145 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32);
sblair 0:f09b7bb8bcce 146 }
sblair 0:f09b7bb8bcce 147
sblair 0:f09b7bb8bcce 148 return offset + len;
sblair 0:f09b7bb8bcce 149 }
sblair 0:f09b7bb8bcce 150 int BER_DECODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
sblair 0:f09b7bb8bcce 151 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 152 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 153
sblair 0:f09b7bb8bcce 154 if (buf[offset++] == ASN1_TAG_UNSIGNED) {
sblair 0:f09b7bb8bcce 155 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 156 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 157
sblair 0:f09b7bb8bcce 158 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT16U);
sblair 0:f09b7bb8bcce 159 }
sblair 0:f09b7bb8bcce 160
sblair 0:f09b7bb8bcce 161 return offset + len;
sblair 0:f09b7bb8bcce 162 }
sblair 0:f09b7bb8bcce 163 int BER_DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
sblair 0:f09b7bb8bcce 164 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 165 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 166
sblair 0:f09b7bb8bcce 167 if (buf[offset++] == ASN1_TAG_UNSIGNED) {
sblair 0:f09b7bb8bcce 168 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 169 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 170
sblair 0:f09b7bb8bcce 171 ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
sblair 0:f09b7bb8bcce 172 }
sblair 0:f09b7bb8bcce 173
sblair 0:f09b7bb8bcce 174 return offset + len;
sblair 0:f09b7bb8bcce 175 }
sblair 0:f09b7bb8bcce 176 int BER_DECODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
sblair 0:f09b7bb8bcce 177 netmemcpy(value, buf, SV_GET_LENGTH_VISSTRING255);
sblair 0:f09b7bb8bcce 178
sblair 0:f09b7bb8bcce 179 return SV_GET_LENGTH_VISSTRING255;
sblair 0:f09b7bb8bcce 180 }
sblair 0:f09b7bb8bcce 181 int BER_DECODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
sblair 0:f09b7bb8bcce 182 CTYPE_INT16U offset = 0;
sblair 0:f09b7bb8bcce 183 CTYPE_INT16U len = 0;
sblair 0:f09b7bb8bcce 184
sblair 0:f09b7bb8bcce 185 if (buf[offset++] == ASN1_TAG_BOOLEAN) {
sblair 0:f09b7bb8bcce 186 len += decodeLength(&buf[offset]);
sblair 0:f09b7bb8bcce 187 offset += getLengthFieldSize(buf[offset]);
sblair 0:f09b7bb8bcce 188
sblair 0:f09b7bb8bcce 189 netmemcpy(value, &buf[offset], len);
sblair 0:f09b7bb8bcce 190 }
sblair 0:f09b7bb8bcce 191
sblair 0:f09b7bb8bcce 192 return offset + len;
sblair 0:f09b7bb8bcce 193 }
sblair 0:f09b7bb8bcce 194 int BER_DECODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
sblair 0:f09b7bb8bcce 195 netmemcpy(value, buf, SV_GET_LENGTH_DBPOS);
sblair 0:f09b7bb8bcce 196
sblair 0:f09b7bb8bcce 197 return SV_GET_LENGTH_DBPOS;
sblair 0:f09b7bb8bcce 198 }