Files
CCU621M/app/pos_vtk/vtk_tlv.c
T

168 lines
4.1 KiB
C
Raw 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.
#include "pos_vtk/vtk_tlv.h"
#include "publicdata/public_define.h"
#include <string.h>
#if (POS_VTK_EN)
/******************************************************************************
* 模块说明:VTK TLV 编解码工具
*
* - 仅支持简单的 TLV 格式:1 字节 Tag + 1 字节 Length + Value。
* - 用于构造 VTK 应用层 TLV 消息(例如 Message name、Operation number、Amount)。
*
* 对外接口:
* - vtk_tlv_append() :追加任意二进制 TLV。
* - vtk_tlv_append_ascii() :追加 ASCII 字符串 TLV。
* - vtk_tlv_append_ascii_uint(): 以十进制 ASCII 形式追加整数 TLV。
* - vtk_tlv_find_first() :在 TLV 缓冲中查找首个指定 Tag。
******************************************************************************/
U8_T vtk_tlv_append(U8_T tag, const U8_T *pVal, U16_T len,
U8_T *pBuf, U16_T bufMax, U16_T *pOffset)
{
U16_T offset;
if (!pBuf || !pOffset)
return 0;
offset = *pOffset;
/* 仅支持短格式长度(1 字节,len < 128 */
if (len > 127U)
return 0;
if ((U16_T)(offset + 2U + len) > bufMax)
return 0;
pBuf[offset++] = tag;
pBuf[offset++] = (U8_T)len;
if (len > 0U && pVal)
{
(void)memcpy(&pBuf[offset], pVal, len);
offset = (U16_T)(offset + len);
}
*pOffset = offset;
return 1;
}
U8_T vtk_tlv_append_ascii(U8_T tag, const char *str,
U8_T *pBuf, U16_T bufMax, U16_T *pOffset)
{
U16_T len;
if (!str)
return 0;
len = (U16_T)strlen(str);
return vtk_tlv_append(tag, (const U8_T *)str, len, pBuf, bufMax, pOffset);
}
/* 把无符号整数转换为十进制 ASCII(不带 '\0'),右对齐或自然长度 */
static U8_T vtk_utoa_dec(U32_T value, char *out, U8_T minWidth)
{
char buf[16];
U8_T i = 0U;
U8_T len;
if (!out)
return 0;
/* 生成反向字符串 */
do
{
buf[i++] = (char)('0' + (value % 10U));
value /= 10U;
} while (value != 0U && i < sizeof(buf));
/* 实际长度至少为 minWidth */
while (i < minWidth && i < sizeof(buf))
{
buf[i++] = '0';
}
len = i;
/* 反转到输出缓冲 */
while (i > 0U)
{
*out++ = buf[--i];
}
return len;
}
U8_T vtk_tlv_append_ascii_uint(U8_T tag, U32_T value, U8_T minWidth,
U8_T *pBuf, U16_T bufMax, U16_T *pOffset)
{
char tmp[16];
U8_T len;
len = vtk_utoa_dec(value, tmp, minWidth);
if (len == 0U)
return 0;
return vtk_tlv_append(tag, (const U8_T *)tmp, len, pBuf, bufMax, pOffset);
}
U8_T vtk_tlv_find_first(const U8_T *pBuf, U16_T bufLen, U8_T tag,
const U8_T **ppVal, U16_T *pValLen)
{
U16_T offset = 0U;
if (!pBuf || !ppVal || !pValLen)
return 0;
while (offset + 2U <= bufLen)
{
U8_T t = pBuf[offset];
U8_T l = pBuf[offset + 1U];
U16_T next;
next = (U16_T)(offset + 2U + l);
if (next > bufLen)
return 0; /* TLV 结构损坏 */
if (t == tag)
{
*ppVal = &pBuf[offset + 2U];
*pValLen = l;
return 1;
}
offset = next;
}
return 0;
}
/*
* 外部使用示例:
*
* // 构造 TLV 缓冲用于预扣款请求(CDP)
* U8_T tlvBuf[VTK_MAX_APP_LEN];
* U16_T tlvLen = 0;
*
* // Tag 0x01: Message name = "CDP"
* vtk_tlv_append_ascii(0x01, "CDP", tlvBuf, sizeof(tlvBuf), &tlvLen);
*
* // Tag 0x03: Operation number = "12345"
* vtk_tlv_append_ascii_uint(0x03, 12345U, 1U, tlvBuf, sizeof(tlvBuf), &tlvLen);
*
* // Tag 0x04: Amount = "5000" (单位:分)
* vtk_tlv_append_ascii_uint(0x04, 5000U, 1U, tlvBuf, sizeof(tlvBuf), &tlvLen);
*
* // 解析响应时查找结果码(假设结果码放在 Tag 0x0D 的 Simple data block 首字节)
* const U8_T *pVal;
* U16_T valLen;
* if (vtk_tlv_find_first(tlvBuf, tlvLen, 0x0D, &pVal, &valLen) && valLen > 0U)
* {
* U8_T resultCode = pVal[0];
* // 0=Approved, 1=Declined, 2=Timeout...
* }
*/
#endif /* POS_VTK_EN */