1、新增Dengle定时参数下发功能,支持最多10条配置,断电保存到Flash,COM打开时暂停发送、关闭后恢复

2、新增USB查询产品码(0x66)和查询Dengle配置(0x74)命令
3、修复bleproto组包栈溢出导致设置Dengle后复位的问题,并完善CDC的DTR状态判断
This commit is contained in:
2026-07-31 14:54:26 +08:00
parent 79e15a9ccc
commit 2260768167
38 changed files with 1742 additions and 717 deletions
+164 -6
View File
@@ -15,6 +15,7 @@
#include "vm.h"
#include "usr_usb_jb.h"
#include "bleproto_api.h"
#include "usr_dengle_sched.h"
#define LOG_TAG_CONST APP
#define LOG_TAG "[USB_JB]"
@@ -36,6 +37,7 @@
#define PKT_HEAD_1 0xAA
#define MAX_PACKAGE_LEN 128
#define JB_RB_CAPACITY 256
#define JB_RSP_BUF_SZ 800 /* Dengle 查询应答:result + 最多 10 槽 */
#define USR_PROD_MAGIC 0x5A
#define USR_JB_BLE_CMD_REPORT 100 /* 0x07/0x34/0x38 → 主动上报类 */
#define USR_JB_BLE_CMD_ACK 110 /* 0x04/0x06/0x31/0x37 → 应答类 */
@@ -86,6 +88,7 @@ static uint8_t s_pending_pcode[USR_PCODE_LEN];
static int s_process_timer;
static uint8_t s_ble_txbuf[USR_JB_BLE_TX_SZ];
static uint8_t s_last_ble_msgid; /* 最近一次 BLE RX 的 msgid */
static uint8_t s_rsp_buf[JB_RSP_BUF_SZ];
void usr_ble_rx_msgid_save(uint8_t msgid)
{
@@ -426,6 +429,117 @@ static void usr_jb_send_ack(uint8_t cmd, uint8_t sn, uint8_t result)
buf[7] = usr_jb_checksum(buf, total);
cdc_write_data(0, buf, total);
}
/**
* @brief 回带 payload 的应答:CMD = 请求 CMD+1
* @param cmd 请求命令
* @param sn 流水号
* @param payload 应答负载(可为 NULL)
* @param payload_len 负载长度
*/
static void usr_jb_send_rsp(uint8_t cmd, uint8_t sn,
const uint8_t *payload, uint16_t payload_len)
{
uint16_t len_field;
uint16_t total;
/* LEN = CMD + SN + payload + CKSUM */
len_field = (uint16_t)(2 + payload_len + 1);
total = (uint16_t)(len_field + 4);
if (total > JB_RSP_BUF_SZ) {
printf("usr_jb rsp too long %u\n", total);
usr_jb_send_ack(cmd, sn, 0x01);
return;
}
s_rsp_buf[0] = PKT_HEAD_0;
s_rsp_buf[1] = PKT_HEAD_1;
s_rsp_buf[2] = (uint8_t)(len_field >> 8);
s_rsp_buf[3] = (uint8_t)(len_field & 0xFF);
s_rsp_buf[4] = (uint8_t)(cmd + 1);
s_rsp_buf[5] = sn;
if (payload && payload_len) {
memcpy(&s_rsp_buf[6], payload, payload_len);
}
s_rsp_buf[total - 1] = usr_jb_checksum(s_rsp_buf, total);
cdc_write_data(0, s_rsp_buf, total);
printf("usr_jb rsp cmd=0x%02x plen=%u total=%u\n", cmd + 1, payload_len, total);
}
/**
* @brief Dengle 查询:空/0xFF=全部;单字节槽位=查一条
* @note 应答 0x75
* 查全部 → [result][slot_rec x 10]slot_rec 与 0x70 payload 同格式
* 查单槽 → [result][slot_rec x 1]
*/
static void usr_jb_handle_dengle_query(uint8_t sn,
const uint8_t *payload,
uint16_t payload_len)
{
static uint8_t s_body[JB_RSP_BUF_SZ - 8];
int n;
uint8_t slot_id;
uint8_t i;
/* 查单槽 */
if (payload_len >= 1 && payload[0] < DENGLE_SLOT_MAX) {
slot_id = payload[0];
s_body[0] = 0x00; /* result ok */
n = dengle_sched_pack_slot(slot_id, &s_body[1], sizeof(s_body) - 1);
if (n <= 0) {
usr_jb_send_ack(USR_JB_CMD_DENGLE_QRY, sn, 0x01);
return;
}
usr_jb_send_rsp(USR_JB_CMD_DENGLE_QRY, sn, s_body, (uint16_t)(1 + n));
return;
}
/* 查全部:payload 空 / 0xFF / 其它 */
s_body[0] = 0x00;
n = dengle_sched_pack_all(&s_body[1], sizeof(s_body) - 1);
if (n > 0) {
usr_jb_send_rsp(USR_JB_CMD_DENGLE_QRY, sn, s_body, (uint16_t)(1 + n));
return;
}
/* 缓冲不够时退化为逐槽上报 */
printf("dengle qry pack_all fail, fallback per-slot\n");
for (i = 0; i < DENGLE_SLOT_MAX; i++) {
s_body[0] = 0x00;
n = dengle_sched_pack_slot(i, &s_body[1], sizeof(s_body) - 1);
if (n <= 0) {
usr_jb_send_ack(USR_JB_CMD_DENGLE_QRY, sn, 0x01);
return;
}
usr_jb_send_rsp(USR_JB_CMD_DENGLE_QRY, sn, s_body, (uint16_t)(1 + n));
}
}
/**
* @brief 查询产品码:应答格式与 0x64 设置 payload 对齐(带 result
* RSP 0x67 payload:
* [result:1][04][ProdtCode 4B][06][productCode 6B]
*/
static void usr_jb_handle_prodcode_query(uint8_t sn)
{
uint8_t body[1 + 1 + USR_PRODCODE_LEN + 1 + USR_PCODE_LEN];
uint8_t prod[USR_PRODCODE_LEN];
uint8_t pcode[USR_PCODE_LEN];
usr_prodcode_get(prod, pcode);
body[0] = 0x00; /* result ok */
body[1] = USR_PRODCODE_LEN;
memcpy(&body[2], prod, USR_PRODCODE_LEN);
body[2 + USR_PRODCODE_LEN] = USR_PCODE_LEN;
memcpy(&body[2 + USR_PRODCODE_LEN + 1], pcode, USR_PCODE_LEN);
printf("prodcode qry: %c%c%c%c / %c%c%c%c%c%c\n",
prod[0], prod[1], prod[2], prod[3],
pcode[0], pcode[1], pcode[2], pcode[3], pcode[4], pcode[5]);
usr_jb_send_rsp(USR_JB_CMD_GET_PRODCODE, sn, body, sizeof(body));
}
#endif
/**
@@ -458,25 +572,59 @@ static void usr_jb_process_timeout(void *priv)
printf("usr_jb cmd=0x%02x sn=%u plen=%u\n", cmd, sn, payload_len);
printf_buf(pkt, pkt_len);
if (cmd == USR_JB_CMD_SET_PRODCODE) {
switch (cmd) {
case USR_JB_CMD_SET_PRODCODE:
if (usr_jb_parse_prod_payload(&pkt[6], payload_len,
s_pending_prod, s_pending_pcode) != 0) {
printf("usr_jb set prodcode payload invalid\n");
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_send_ack(cmd, sn, 0x01);
#endif
continue;
break;
}
/* 缓存后统一落盘,避免同一周期多次写 flash */
s_pending_cmd = cmd;
s_pending_sn = sn;
s_pending_save = 1;
continue;
break;
case USR_JB_CMD_GET_PRODCODE:
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_handle_prodcode_query(sn);
#endif
break;
case USR_JB_CMD_DENGLE_SET: {
Dengle_Ret_t dr = dengle_sched_usb_set(&pkt[6], payload_len);
printf("dengle sched usb set ret=%d\n", dr);
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_send_ack(cmd, sn, (dr == DENGLE_OK) ? 0x00 : 0x01);
#endif
break;
}
/* 其它命令:整帧透传到 BLE(按 JB cmd 映射 ble_proto cmd */
usr_jb_forward_to_ble(pkt, pkt_len);
case USR_JB_CMD_DENGLE_CLR: {
Dengle_Ret_t dr = dengle_sched_clear_all();
printf("dengle sched clear all ret=%d\n", dr);
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_send_ack(cmd, sn, (dr == DENGLE_OK) ? 0x00 : 0x01);
#endif
break;
}
case USR_JB_CMD_DENGLE_QRY:
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_handle_dengle_query(sn, &pkt[6], payload_len);
#else
(void)payload_len;
#endif
break;
default:
/* 其它命令:整帧透传到 BLE(按 JB cmd 映射 ble_proto cmd */
usr_jb_forward_to_ble(pkt, pkt_len);
break;
}
} while (1);
if (!s_pending_save) {
@@ -484,6 +632,16 @@ static void usr_jb_process_timeout(void *priv)
}
s_pending_save = 0;
/* code / prodcode 与当前完全一致:ACK 成功,不写 Flash、不重建广播 */
if (memcmp(s_prodcode, s_pending_prod, USR_PRODCODE_LEN) == 0 &&
memcmp(s_pcode, s_pending_pcode, USR_PCODE_LEN) == 0) {
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_send_ack(s_pending_cmd, s_pending_sn, 0x00);
#endif
printf("prodcode unchanged, skip adv rebuild\n");
return;
}
if (usr_prodcode_save(s_pending_prod, s_pending_pcode) == 0) {
#if TCFG_USB_SLAVE_CDC_ENABLE
usr_jb_send_ack(s_pending_cmd, s_pending_sn, 0x00);