9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
168 lines
4.1 KiB
C
168 lines
4.1 KiB
C
#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 */
|
||
|