326 lines
12 KiB
C
326 lines
12 KiB
C
/****************************************************************************/
|
||
/* 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
|