/****************************************************************************/ /* Copyright (c) 2007,许继集团有限公司 */ /* All rights reserved. */ /* */ /* 模块描述: */ /** asn1数据快速取值和设值接口 * @file gsv_asn1.h */ /* */ /* 日期 作者 注释 */ /* 2007/12/10 DJF 创建文件 */ /****************************************************************************/ #ifndef GSMV_GSV_ASN1_INC #define GSMV_GSV_ASN1_INC #include "glbtypes.h" #include "sysincs.h" #include "as_damap.h" #include "gse_rx.h" #ifdef __cplusplus extern "C" { #endif /** ASN.1 简单单元信息 */ typedef struct ASN_1_UNIT_struct { ST_UINT16 tag; /**< 单元标签 */ ST_UINT16 size; /**< 单元数据长度 */ ST_UINT16 offset; /**< 在数据流中,相对于asn1数据起始位置的偏移量 */ } ASN_1_UNIT, * PASN_1_UNIT; /** Goose 报文头成员标签值 */ #define TAG_GS_gocbRef 0 #define TAG_GS_timeToLive 1 #define TAG_GS_dataSet 2 #define TAG_GS_goId 3 #define TAG_GS_t 4 #define TAG_GS_stNum 5 #define TAG_GS_sqNum 6 #define TAG_GS_test 7 #define TAG_GS_confRev 8 #define TAG_GS_ndsCom 9 #define TAG_GS_entryNum 10 #define TAG_GS_MAX 10 /** SMV-9-2 ASDU头成员标签index */ #define TAG_SMV_NOASDU 0 #define TAG_SMV_ASDU_svID 0 #define TAG_SMV_ASDU_DatSet 1 #define TAG_SMV_ASDU_SmpCnt 2 #define TAG_SMV_ASDU_ConfRev 3 #define TAG_SMV_ASDU_RefrTm 4 #define TAG_SMV_ASDU_SmpSynch 5 #define TAG_SMV_ASDU_SmpRate 6 #define TAG_SMV_ASDU_ENTRY 7 /**< entry内是数据集数据 */ /** ASN1编码后数组的最大值 */ #define ASN1_UNITS_MAX 400 /************************************************************************/ /* 快速 asn.1 编码解码 */ /************************************************************************/ #define asn1_GetBOOL(pdata, punit, value) \ { \ value = pdata[(punit)->offset] & 0x01; \ } #define asn1_SetBOOL(pdata, punit, value) \ { \ pdata[(punit)->offset] = value & 0x01; \ } /************************************************************************ * 如何从整形的asn1编码判断正负数 * 答:asn1规定,当数据域长度为4个字节时,如果最高字节的最高位为1,则指定 * 是负整数,否则是正整数。当数据域长度为5个字节时,表示正整数,对应无符号 * 型正数,且最高字节值为0,次高字节的最高位为1 ************************************************************************/ /** * 下面全是asn1编码数据的读写接口,为性能起见,使用宏定义代替函数 * @param pdata asn1编码数据的地址,要和调用asn1_Parse解析时传入的参数保持一致 * @param punit asn1简单数据单元,ASN_1_UNIT类型,由asn1_parse得到 * @param value 从punit中读到的值或要写到punit中的值 */ #define asn1_GetINT(pdata, punit, value) \ { \ PASN_1_UNIT pu = punit; \ ST_UINT8 * p = &pdata[pu->offset]; \ ST_UINT size = pu->size; \ ST_INT v; \ if (size == 4) \ { \ v = (* p++) << 24; \ v |= (* p++) << 16; \ v |= (* p++) << 8; \ v |= (* p); \ } \ else \ { \ v = * p & 0x80 ? 0xFFFFFF00 : 0; \ while (1) \ { \ v |= (* p++) & 0xFF; \ if (--size == 0) \ break; \ v <<= 8; \ } \ } \ value = v; \ } #define asn1_SetINT(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_INT v = value; \ * p++ = (v >> 24) & 0xFF; \ * p++ = (v >> 16) & 0xFF; \ * p++ = (v >> 8) & 0xFF; \ * p = v & 0xFF; \ } #define asn1_GetUINT(pdata, punit, value) \ { \ PASN_1_UNIT pu = punit; \ ST_UINT8 * p = &pdata[pu->offset]; \ ST_UINT size = pu->size; \ ST_UINT v = 0; \ while (1) \ { \ v |= (* p++) & 0xFF; \ if (--size == 0) \ break; \ v <<= 8; \ } \ value = v; \ } #define asn1_SetUINT(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_UINT v = value; \ if((punit)->size == 5) \ { \ * p++ = 0; \ } \ * p++ = (v >> 24) & 0xFF; \ * p++ = (v >> 16) & 0xFF; \ * p++ = (v >> 8) & 0xFF; \ * p = v & 0xFF; \ } #define asn1_GetFLOAT(pdata, punit, value) \ { \ if (SD_BYTE_ORDER == SD_LITTLE_ENDIAN) \ { \ ST_UINT8 * psrc = &pdata[(punit)->offset] + 4; \ ST_FLOAT v ; \ ST_UINT8 * p = ( ST_UINT8 * )&v; \ * p++ = *psrc--; \ * p++ = *psrc--; \ * p++ = *psrc--; \ * p = *psrc; \ value = v; \ } \ else \ { \ ST_UINT8 * psrc = &pdata[(punit)->offset] + 1; \ ST_FLOAT v ; \ ST_UINT8 * p = ( ST_UINT8 * )&v; \ * p++ = *psrc++; \ * p++ = *psrc++; \ * p++ = *psrc++; \ * p = *psrc; \ value = v; \ } \ } #define asn1_SetFLOAT(pdata, punit, value) \ { \ if (SD_BYTE_ORDER == SD_LITTLE_ENDIAN) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_FLOAT v = value; \ ST_UINT8 * psrc = ( ST_UINT8 * )&v; \ * p++ = 8; \ * p++ = *psrc++; \ * p++ = *psrc++; \ * p++ = *psrc++; \ * p = *psrc; \ } \ else \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_FLOAT v = value; \ ST_UINT8 * psrc = ( ST_UINT8 * )&v + 3; \ * p++ = 8; \ * p++ = *psrc--; \ * p++ = *psrc--; \ * p++ = *psrc--; \ * p = *psrc; \ } \ } #define asn1_GetUTC(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_INT v; \ v = (* p++) << 24; \ v |= (* p++) << 16; \ v |= (* p++) << 8; \ v |= (* p++); \ value.secs = v; \ v = (* p++) << 16; \ v |= (* p++) << 8; \ v |= (* p++); \ value.fraction = v; \ value.qflags = * p; \ } #define asn1_SetUTC(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_INT v; \ v = value.secs; \ * p++ = (ST_UCHAR)((v >> 24) & 0xFF); \ * p++ = (ST_UCHAR)((v >> 16) & 0xFF); \ * p++ = (ST_UCHAR)((v >> 8) & 0xFF); \ * p++ = (ST_UCHAR)(v & 0xFF); \ v = value.fraction; \ * p++ = (ST_UCHAR)((v >> 16) & 0xFF); \ * p++ = (ST_UCHAR)((v >> 8) & 0xFF); \ * p++ = (ST_UCHAR)(v & 0xFF); \ * p = (ST_UCHAR)(value.qflags & 0xFF); \ } #define asn1_GetBstr13(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset] + 1; \ value[0] = * p++; \ value[1] = * p; \ } #define asn1_SetBstr13(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ * p++ = 0x03; \ * p++ = value[0]; \ * p = value[1]; \ } #define asn1_GetBstr2(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ value[0] = *(p+1); \ } #define asn1_SetBstr2(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ * p++ = 0x06; \ * p = value[0]; \ } #define asn1_GetEntryTime(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_INT v; \ v = (* p++) << 24; \ v |= (* p++) << 16; \ v |= (* p++) << 8; \ v |= (* p++); \ value.btime6_ms = v; \ v = (* p++) << 8; \ v |= (* p); \ value.btime6_days = v; \ } #define asn1_SetEntryTime(pdata, punit, value) \ { \ ST_UINT8 * p = &pdata[(punit)->offset]; \ ST_INT v; \ v = value.btime6_ms; \ * p++ = (ST_UCHAR)((v >> 24) & 0xFF); \ * p++ = (ST_UCHAR)((v >> 16) & 0xFF); \ * p++ = (ST_UCHAR)((v >> 8) & 0xFF); \ * p++ = (ST_UCHAR)(v & 0xFF); \ v = value.btime6_days; \ * p++ = (ST_UCHAR)((v >> 8) & 0xFF); \ * p = (ST_UCHAR)(v & 0xFF); \ } /** * 将 asn.1 编码的数据解析为线性元素数组 * @param data asn.1编码数据 * @param datalen 数据长度。 * @param unit 基本数据单元信息数组 * @param maxnum unit数组的最大个数 * @return 实际解析出来的单元个数,出错返回 0 **/ ST_INT asn1_Parse( ST_UINT8 * data, ST_INT datalen, ASN_1_UNIT * unit, ST_INT maxnum ); /** * 把GSV_UNIT_DATA类型的值写到ASN_1_UNIT中 * @param asn1buf 调用asn1_parse时传入的asn1数据指针,用于计算aunits中的数据偏移 * @param gunits GSV_UNIT_DATA类型的数据,数组 * @param num 数组成员个数 * @param aunits ASN_1_UNIT类型的数据,数组 **/ //ST_VOID gsv_set_asn1_unit_val(ST_UCHAR *asn1buf, GSV_UNIT_DATA *gunits, ST_INT num, ASN_1_UNIT *aunits); /** * 从ASN_1_UNIT中读值到DATA_MAP中 * @param asn1buf 调用asn1_parse时传入的asn1数据指针,用于计算aunits中的数据偏移 * @param aunits ASN_1_UNIT类型的数据,数组 * @param num 数组成员个数 * @param goosemap数组,成员da_map_num可能==0,da_maps可能 == NULL **/ ST_RET gse_get_asn1_unit_val( ST_UCHAR * asn1buf, ASN_1_UNIT * aunits, ST_INT num, GOOSE_MAP_CTRL * goose_maps ); #ifdef __cplusplus } #endif #endif