在蓝牙协议栈开发过程中,有时需要预先知道 LLCP。本文将介绍如何利用 trace 机制实现 LLCP 预览功能。
实现原理
打开 trace PLATFORM_TRACE_ID_LLCP
类型,Controller 会在接收到 LLCP 时通过 trace 回调函数导出数据。
我们可以在回调函数里截获 PLATFORM_TRACE_ID_LLCP
,并预览数据。这个的“预览”包含两层含义:
- Controller 尚未处理该 PDU(Controller 将于 trace 回调完成后处理 PDU);
- 只可读取 PDU 内容,不可修改。
让我们详细介绍实现方法。
1. Trace 数据结构
PLATFORM_TRACE_ID_LLCP
trace 类型使用的头信息结构如下:
#pragma pack (push, 1)
typedef struct
{
uint32_t A;
uint32_t B;
uint8_t id;
uint8_t tag;
} header_t;
#pragma pack (pop)
这个结构使用 #pragma pack (push, 1)
指令确保内存对齐。
2. Trace 回调处理
假设 cb_trace_read_llcp
函数为 trace 回调函数,在函数开头添加代码截获接收到的 LLCP:
static uint32_t cb_trace_read_llcp(const platform_evt_trace_t *trace, trace_rtt_t *ctx)
{
if (trace->len1 == sizeof(header_t))
{
const header_t *p = (const header_t *)trace->data1;
if ((p->id == PLATFORM_TRACE_ID_LLCP) && (p->tag & 1))
{
const uint8_t *p8 = (const uint8_t *)trace->data2;
llcp_preview(p->tag >> 1, p8[0], p8 + 1, trace->len2 - 1);
}
}
// ...
return 0;
}
3. PDU 预览显示
llcp_preview
函数负责预览 LLCP。下面的参考代码打印了关于 LLCP 的完整信息:
- 连接句柄(handle)
- 操作码(op_code)
- 控制数据
static void llcp_preview(hci_con_handle_t handle, uint8_t op_code, const uint8_t *ctr_data, int ctr_data_len)
{
platform_printf("LLCP[%d] OP %02x: ", handle, op_code);
printf_hexdump(ctr_data, ctr_data_len);
platform_printf("\n");
}
总结
利用 trace 机制实现的 PDU 预览功能,能帮助开发者实时监控 LLCP 通信,实现必要功能。