2025-04-30 16:24:29 +08:00

326 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************/
/* 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