Steven Blair / rapid61850example
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gseEncodeBasic.c Source File

gseEncodeBasic.c

00001 /**
00002  * Rapid-prototyping protection schemes with IEC 61850
00003  *
00004  * Copyright (c) 2011 Steven Blair
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #ifndef GSE_BER_ENCODE_BASIC_C
00022 #define GSE_BER_ENCODE_BASIC_C
00023 
00024 #include "ctypes.h"
00025 #include "datatypes.h"
00026 #include "ied.h"
00027 #include "gseEncodeBasic.h"
00028 
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 
00032 // BER encoding of basic types
00033 int BER_ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
00034     CTYPE_INT16U offset = 0;
00035     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT32(value);
00036 
00037     buf[offset++] = ASN1_TAG_FLOATING_POINT;
00038     offset += encodeLength(&buf[offset], len);
00039 
00040     buf[offset++] = 0x08;    // bits for exponent
00041     netmemcpy(&buf[offset], value, len - 1);
00042 
00043     return offset + len - 1;
00044 }
00045 int BER_ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
00046     CTYPE_INT16U offset = 0;
00047     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT64(value);
00048 
00049     buf[offset++] = ASN1_TAG_FLOATING_POINT;
00050     offset += encodeLength(&buf[offset], len);
00051 
00052     buf[offset++] = 0x0B;    // bits for exponent
00053     netmemcpy(&buf[offset], value, len - 1);
00054 
00055     return offset + len - 1;
00056 }
00057 int BER_ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
00058     CTYPE_INT16U offset = 0;
00059     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_QUALITY(value);
00060 
00061     buf[offset++] = ASN1_TAG_BIT_STRING;
00062     offset += encodeLength(&buf[offset], len - 1);
00063 
00064     buf[offset++] = QUALITY_UNUSED_BITS;    // number of unused bits
00065     netmemcpy(&buf[offset], value, len - 1);
00066 
00067     return offset + len - 1;
00068 }
00069 int BER_ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
00070     CTYPE_INT16U offset = 0;
00071     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_TIMESTAMP(value);
00072 
00073     buf[offset++] = ASN1_TAG_OCTET_STRING;
00074     offset += encodeLength(&buf[offset], len);
00075 
00076     memcpy(&buf[offset], value, len);    //TODO should be memcpy, because already in big-endian?
00077 
00078     return offset + len;
00079 }
00080 int BER_ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {    // assuming enum is an int - allows any enum type to be used
00081     CTYPE_INT16U offset = 0;
00082     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_ENUM(value);
00083 
00084     buf[offset++] = ASN1_TAG_INTEGER;
00085     offset += encodeLength(&buf[offset], len);
00086 
00087     ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);
00088     //netmemcpy(&buf[offset], value, len);
00089 
00090     return offset + len;
00091 }
00092 int BER_ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
00093     CTYPE_INT16U offset = 0;
00094     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16(value);
00095 
00096     buf[offset++] = ASN1_TAG_INTEGER;
00097     offset += encodeLength(&buf[offset], len);
00098 
00099     ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16);
00100     //netmemcpy(&buf[offset], value, len);
00101 
00102     return offset + len;
00103 }
00104 int BER_ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
00105     CTYPE_INT16U offset = 0;
00106     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32(value);
00107 
00108     buf[offset++] = ASN1_TAG_INTEGER;
00109     offset += encodeLength(&buf[offset], len);
00110 
00111     printf("INT32 value: %u, len: %i, total: %i\n", *value, len, offset + len);
00112     fflush(stdout);
00113     ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32);
00114     //netmemcpy(&buf[offset], value, len);
00115 
00116     return offset + len;
00117 }
00118 int BER_ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
00119     CTYPE_INT16U offset = 0;
00120     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16U(value);
00121 
00122     buf[offset++] = ASN1_TAG_UNSIGNED;
00123     offset += encodeLength(&buf[offset], len);
00124 
00125     printf("INT16U value: %u, len: %i, total: %i\n", *value, len, offset + len);
00126     fflush(stdout);
00127     ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16U);
00128     //netmemcpy(&buf[offset], value, len);
00129 
00130     return offset + len;
00131 }
00132 int BER_ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
00133     CTYPE_INT16U offset = 0;
00134     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32U(value);
00135 
00136     buf[offset++] = ASN1_TAG_UNSIGNED;
00137     offset += encodeLength(&buf[offset], len);
00138 
00139     ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);
00140 
00141     printf("INT32U value: %u, len: %i, total: %i\n", *value, len, offset + len);
00142     fflush(stdout);
00143     //netmemcpy(&buf[offset], value, len);
00144 
00145     return offset + len;
00146 }
00147 int BER_ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
00148     netmemcpy(buf, value, BER_GET_LENGTH_CTYPE_VISSTRING255(value));
00149 
00150     return BER_GET_LENGTH_CTYPE_VISSTRING255(value);
00151 }
00152 int BER_ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
00153     CTYPE_INT16U offset = 0;
00154     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_BOOLEAN(value);
00155 
00156     buf[offset++] = ASN1_TAG_BOOLEAN;
00157     offset += encodeLength(&buf[offset], len);
00158 
00159     netmemcpy(&buf[offset], value, len);
00160 
00161     return offset + len;
00162 }
00163 int BER_ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
00164     CTYPE_INT16U offset = 0;
00165     CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_DBPOS(value);
00166 
00167     buf[offset++] = 0x85;
00168     offset += encodeLength(&buf[offset], len);
00169 
00170     netmemcpy(&buf[offset], value, len);    //TODO should be memcpy, because already in big-endian?
00171 
00172     return offset + len;
00173 }
00174 
00175 #endif