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
+4
View File
@@ -1142,6 +1142,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="apps/usr_le_code/usr_usb_jb.h" />
<Unit filename="apps/usr_le_code/usr_dengle_sched.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="apps/usr_le_code/usr_dengle_sched.h" />
<Unit filename="apps/usr_le_code/usr_le_recieve.c">
<Option compilerVar="CC" />
</Unit>
+24 -10
View File
@@ -131622,7 +131622,7 @@
1756104107 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\earphone\board\br28\board_config.h
"board_jl701n_demo_cfg.h"
1784866489 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\earphone\board\br28\board_jl701n_demo_cfg.h
1785398767 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\earphone\board\br28\board_jl701n_demo_cfg.h
"board_jl701n_demo_global_build_cfg.h"
"usb_std_class_def.h"
"usb_std_class_def.h"
@@ -131752,7 +131752,7 @@
1706666735 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\system\power_manage.h
"generic/typedef.h"
1784878367 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\system\syscfg_id.h
1785397241 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\system\syscfg_id.h
"typedef.h"
1706666736 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\system\bank_switch.h
@@ -132394,7 +132394,7 @@
1706666737 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\driver\cpu\br28\asm\sfc_norflash_api.h
"typedef.h"
1706666728 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\device\usb\device\cdc.h
1785402444 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\device\usb\device\cdc.h
"usb/device/usb_stack.h"
1706666736 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\include_lib\driver\device\usb\device\usb_stack.h
@@ -133039,7 +133039,7 @@
"typedef.h"
"device.h"
1706666728 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\device\usb\device\cdc.c
1785402441 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\device\usb\device\cdc.c
"usb/device/usb_stack.h"
"usb/usb_config.h"
"usb/device/cdc.h"
@@ -134230,7 +134230,7 @@
"rcsp_adv_bluetooth.h"
"bt_tws.h"
1785142510 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\third_party_profile\jieli\jl_rcsp\bt_trans_data\le_rcsp_adv_module.c
1785399324 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\common\third_party_profile\jieli\jl_rcsp\bt_trans_data\le_rcsp_adv_module.c
"system/app_core.h"
"system/includes.h"
"app_config.h"
@@ -134919,7 +134919,7 @@
"bt_tws.h"
"icsd_adt_app.h"
1785135433 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\earphone\app_main.c
1785395062 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\earphone\app_main.c
"system/includes.h"
"btstack/btstack_task.h"
"app_config.h"
@@ -136048,7 +136048,7 @@
"ble_proto.h"
<string.h>
1785211820 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\bleproto.c
1785399208 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\bleproto.c
"bleproto.h"
"ble_proto.h"
@@ -136074,7 +136074,7 @@
"usr_usb_jb.h"
"debug.h"
1785221986 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_le_recieve.c
1785398395 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_le_recieve.c
"app_config.h"
"asm/pwm_led.h"
"tone_player.h"
@@ -137191,15 +137191,29 @@
"app_config.h"
"timer.h"
1785222089 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_usb_jb.h
1785470014 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_usb_jb.h
<stdint.h>
1785222977 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_usb_jb.c
1785397251 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_usb_jb.c
"system/includes.h"
"app_config.h"
"vm.h"
"usr_usb_jb.h"
"bleproto_api.h"
"usr_dengle_sched.h"
"debug.h"
"usb/device/cdc.h"
1785402463 source:d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_dengle_sched.c
"system/includes.h"
"app_config.h"
"usr_dengle_sched.h"
"usr_usb_jb.h"
"bleproto_api.h"
"syscfg_id.h"
"usb/device/cdc.h"
"debug.h"
1785402456 d:\jianbao\project\À¶ÑÀת½Ó°å-¶ºÃ¨°ô\sdk\apps\usr_le_code\usr_dengle_sched.h
<stdint.h>
+31 -11
View File
@@ -171,22 +171,25 @@ static u32 cdc_setup(struct usb_device_t *usb_device, struct usb_ctrlrequest *ct
dump_line_coding((struct usb_cdc_line_coding *)cdc_hdl->subtype_data);
break;
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
log_debug("set control line state - %d", ctrl_req->wValue);
/* wValue.bit0=DTR(打开COM通常置1), bit1=RTS */
log_info("set control line state wValue=0x%04x DTR=%d RTS=%d",
ctrl_req->wValue,
!!(ctrl_req->wValue & BIT(0)),
!!(ctrl_req->wValue & BIT(1)));
if (cdc_hdl) {
/* if (ctrl_req->wValue & BIT(0)) { //DTR */
if (ctrl_req->wValue & BIT(0)) { /* DTR */
cdc_hdl->bmTransceiver |= BIT(0);
/* } else { */
/* usb_slave->cdc->bmTransceiver &= ~BIT(0); */
/* } */
/* if (ctrl_req->wValue & BIT(1)) { //RTS */
} else {
cdc_hdl->bmTransceiver &= ~BIT(0);
}
if (ctrl_req->wValue & BIT(1)) { /* RTS */
cdc_hdl->bmTransceiver |= BIT(1);
/* } else { */
/* usb_slave->cdc->bmTransceiver &= ~BIT(1); */
/* } */
cdc_hdl->bmTransceiver |= BIT(4); //cfg done
} else {
cdc_hdl->bmTransceiver &= ~BIT(1);
}
cdc_hdl->bmTransceiver |= BIT(4); /* cfg done */
}
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
//cdc_endpoint_init(usb_device, (ctrl_req->wIndex & USB_RECIP_MASK));
break;
default:
log_error("unsupported class req");
@@ -238,6 +241,10 @@ static void cdc_reset(struct usb_device_t *usb_device, u32 itf)
{
log_error("%s()", __func__);
const usb_dev usb_id = usb_device2id(usb_device);
/* USB 复位/重枚举时清掉 COM 开闭状态 */
if (cdc_hdl) {
cdc_hdl->bmTransceiver &= ~(BIT(0) | BIT(1));
}
#if USB_ROOT2
usb_disable_ep(usb_id, CDC_DATA_EP_IN);
#if CDC_INTR_EP_ENABLE
@@ -487,4 +494,17 @@ void cdc_release(const usb_dev usb_id)
}
}
/**
* @brief 上位机是否已打开 COMCDC DTR 有效)
* @return 1=COM 已打开 0=未打开/已关闭
*/
u8 cdc_is_com_open(void)
{
if (cdc_hdl == NULL) {
return 0;
}
/* DTR=1 表示主机打开了虚拟串口 */
return (cdc_hdl->bmTransceiver & BIT(0)) ? 1 : 0;
}
#endif
+5
View File
@@ -15,6 +15,11 @@ u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len);
u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len);
void cdc_register(const usb_dev usb_id);
void cdc_release(const usb_dev usb_id);
/**
* @brief 上位机是否已打开 COM(依据 CDC DTR
* @return 1=已打开 0=未打开
*/
u8 cdc_is_com_open(void);
#ifdef __cplusplus
}
@@ -522,15 +522,7 @@ void usr_ble_send_data(u8* data,u16 len)
{
app_send_user_data(ATT_CHARACTERISTIC_15f1e601_a277_43fc_a484_dd39ef8a9100_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC);
}
//printf("send rsp:");
// printf_buf(data,len);
printf("\n");
for(u8 i=0;i<len;i++)
{
printf("%c",data[i]);
}
printf("\n");
/* 勿把二进制当字符打到调试串口,否则会出现 $m/-$m 等乱码并拖慢日志 */
}
static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type)
{
+2
View File
@@ -237,7 +237,9 @@ void app_main()
usr_read_device_sta();
{
extern void usr_prodcode_init(void);
extern void dengle_sched_init(void);
usr_prodcode_init();
dengle_sched_init();
}
usr_var.usr_goto_pair = 1;
usr_clear_pair_info_noreset();
+28 -26
View File
@@ -222,91 +222,93 @@ int bleproto_appdata_encode(uint8_t * txbuf,
{
int rc;
uint16_t txbuf_size = size;
/* 原栈上 appdata 约 2KB+,在 USB/定时器回调里极易栈溢出复位,改为静态 */
static bleproto_appdata_t s_enc_appdata;
bleproto_appdata_t *appdata = &s_enc_appdata;
bleproto_appdata_t appdata;
/* header */
{
appdata.header = desc->header;
appdata->header = desc->header;
}
/* data */
if (appdata.header.msgtype == BLEPROTO_APPDATA_MSGTYPE_REQ) {
switch (appdata.header.serviceid) {
if (appdata->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_REQ) {
switch (appdata->header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc = bleproto_encjson_deviceinfo_req(&desc->datast.deviceinfo_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_encjson_authsetup_req(&desc->datast.authsetup_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc = bleproto_encjson_authdelete_req(&desc->datast.authdelete_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_encjson_runcmd_req(&desc->datast.runcmd_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_encjson_reportcmd_req(&desc->datast.reportcmd_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_encjson_doaction_req(&desc->datast.doaction_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_encjson_otanotify_req(&desc->datast.otanotify_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_encjson_otadata_req(&desc->datast.otadata_req,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
rc = ble_proto_pack(&desc->datast.runcmd_v2_req, appdata.data, sizeof(appdata.data));
rc = ble_proto_pack(&desc->datast.runcmd_v2_req, appdata->data, sizeof(appdata->data));
break;
default:
/* unkown serviceid */
return (-1);
}
} else if (appdata.header.msgtype == BLEPROTO_APPDATA_MSGTYPE_RSP) {
switch (appdata.header.serviceid) {
} else if (appdata->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_RSP) {
switch (appdata->header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc = bleproto_encjson_deviceinfo_rsp(&desc->datast.deviceinfo_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_encjson_authsetup_rsp(&desc->datast.authsetup_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc = bleproto_encjson_authdelete_rsp(&desc->datast.authdelete_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_encjson_runcmd_rsp(&desc->datast.runcmd_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_encjson_reportcmd_rsp(&desc->datast.reportcmd_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_encjson_doaction_rsp(&desc->datast.doaction_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_encjson_otanotify_rsp(&desc->datast.otanotify_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_encbin_otadata_rsp(&desc->datast.otadata_rsp,
appdata.data);
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
case E_BLEPROTO_SERVICE_ID_RUNCMD_V2:
rc = ble_proto_pack(&desc->datast.runcmd_v2_rsp, appdata.data, sizeof(appdata.data));
rc = ble_proto_pack(&desc->datast.runcmd_v2_rsp, appdata->data, sizeof(appdata->data));
break;
default:
/* unkown serviceid */
@@ -322,10 +324,10 @@ int bleproto_appdata_encode(uint8_t * txbuf,
}
/* datalen */
appdata.header.datalen = (uint16_t)rc;
appdata->header.datalen = (uint16_t)rc;
/* appdata_serialize */
return bleproto_appdata_serialize(&appdata, packetlen, txbuf, txbuf_size);
return bleproto_appdata_serialize(appdata, packetlen, txbuf, txbuf_size);
}
int bleproto_appdata_decode(uint8_t* rxbuf,
+662
View File
@@ -0,0 +1,662 @@
/******************************************************************************
* @file usr_dengle_sched.c
* @brief Dengle 参数定时下发实现(含 Flash 断电保存)
* @author cyWu <1917507415@qq.com>
* @date 2026.07.30
* @version V1.2.0
* @history
* - V1.0.0, 2026.07.30, cyWu, 首次发布
* - V1.1.0, 2026.07.30, cyWu, 增加 Flash 持久化
* - V1.1.1, 2026.07.30, cyWu, 修复设置后立即发送导致栈溢出复位
* - V1.2.0, 2026.07.30, cyWu, USB 连接时暂停定时发送
* - V1.2.1, 2026.07.30, cyWu, 改为 COM(DTR) 开闭控制暂停/恢复
*
* USB 设置帧 payloadCMD=0x70)格式:
* [0] slot 槽位 0~9
* [1] enable 0=关闭该槽 1=使能
* [2..5] period_ms 发送周期(大端 ms,建议 >=100
* [6..7] cmd_id CBCT/CBFD→ycmd.cmd_id;其它→ble_proto.cmd(大端)
* [8] data_n int 模式= int32 个数;bytes 模式= 字节数
* [9..] data int 模式= data_n 个大端 int32
* bytes 模式= data_n 字节原始数据
*
* 发送策略(按设备当前 prodcode):
* - CBCT / CBFD → REPORTCMD + ycmd.arg_int32[](参考 usr_test_bleproto_runcmd
* - 其它 → REPORTCMD_V2 + bytes_data(参考 usr_test_protocol
******************************************************************************/
#include "system/includes.h"
#include "app_config.h"
#include "usr_dengle_sched.h"
#include "usr_usb_jb.h"
#include "bleproto_api.h"
#include "syscfg_id.h"
#if TCFG_USB_SLAVE_CDC_ENABLE
#include "usb/device/cdc.h"
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[DENGLE]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
/*============================================================================*/
/* 私有宏 */
/*============================================================================*/
#define DENGLE_TX_BUF_SZ (384)
#define DENGLE_PROD_CBCT "CBCT"
#define DENGLE_PROD_CBFD "CBFD"
#define DENGLE_FLASH_MAGIC (0xD6)
#define DENGLE_FLASH_VER (0x01)
#define DENGLE_FLASH_HALF (5) /* 前半/后半各 5 个槽 */
extern void usr_ble_send_data(u8 *data, u16 len);
extern u16 usr_get_conn_service(void);
/*============================================================================*/
/* 私有类型 */
/*============================================================================*/
/** 发送模式:由设备 prodcode 决定 */
typedef enum {
DENGLE_MODE_INT32 = 0, /**< CBCT/CBFDint32 数组 → REPORTCMD */
DENGLE_MODE_BYTES /**< 其它:bytes → REPORTCMD_V2 */
} DengleMode_t;
/** 运行时单条定时配置(含 elapsed,不落盘) */
typedef struct {
uint8_t enable;
uint8_t mode;
uint16_t cmd_id;
uint32_t period_ms;
uint32_t elapsed_ms;
uint8_t data_n;
union {
int32_t i32[DENGLE_INT_MAX];
uint8_t bytes[DENGLE_BYTES_MAX];
} data;
} DengleSlot_t;
/** Flash 单槽结构(不含 elapsed */
typedef struct {
uint8_t enable;
uint8_t mode;
uint16_t cmd_id;
uint32_t period_ms;
uint8_t data_n;
uint8_t data[DENGLE_BYTES_MAX];
} DengleSlotFlash_t;
/** 半区 Flash 块:5 个槽 */
typedef struct {
uint8_t magic;
uint8_t ver;
uint8_t reserved[2];
DengleSlotFlash_t slots[DENGLE_FLASH_HALF];
} DengleFlashHalf_t;
/*============================================================================*/
/* 静态变量 */
/*============================================================================*/
static DengleSlot_t s_slots[DENGLE_SLOT_MAX];
static uint8_t s_inited;
static int s_tick_timer;
static int s_save_timer;
static int s_imm_send_timer;
static uint8_t s_imm_send_slot;
static uint8_t s_txbuf[DENGLE_TX_BUF_SZ];
/* 大结构体放静态区,避免 USB/定时器回调栈溢出 */
static DengleFlashHalf_t s_flash_half;
static bleproto_appdata_desc_t s_encode_desc;
static uint8_t s_usb_pause_logged;
/*============================================================================*/
/* 工具函数 */
/*============================================================================*/
static uint16_t dengle_read_u16_be(const uint8_t *p)
{
return ((uint16_t)p[0] << 8) | p[1];
}
static uint32_t dengle_read_u32_be(const uint8_t *p)
{
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) | p[3];
}
/**
* @brief 根据当前设备 prodcode 选择发送模式
*/
static DengleMode_t dengle_get_mode_by_prodcode(void)
{
uint8_t prod[USR_PRODCODE_LEN];
usr_prodcode_get(prod, NULL);
if (memcmp(prod, DENGLE_PROD_CBCT, USR_PRODCODE_LEN) == 0 ||
memcmp(prod, DENGLE_PROD_CBFD, USR_PRODCODE_LEN) == 0) {
return DENGLE_MODE_INT32;
}
return DENGLE_MODE_BYTES;
}
/**
* @brief 上位机已打开 COM 时暂停 Dengle 定时发送
* @note 设备可一直插着 USB;仅 COM 打开=配置态,COM 关闭后恢复自动发送
* @return 1=应暂停发送 0=允许发送
*/
static uint8_t dengle_is_usb_pause(void)
{
#if TCFG_USB_SLAVE_CDC_ENABLE
return cdc_is_com_open() ? 1 : 0;
#else
return 0;
#endif
}
/*============================================================================*/
/* Flash 读写 */
/*============================================================================*/
/**
* @brief 运行时槽 → Flash 槽
*/
static void dengle_slot_to_flash(const DengleSlot_t *src, DengleSlotFlash_t *dst)
{
memset(dst, 0, sizeof(*dst));
dst->enable = src->enable;
dst->mode = src->mode;
dst->cmd_id = src->cmd_id;
dst->period_ms = src->period_ms;
dst->data_n = src->data_n;
memcpy(dst->data, src->data.bytes, DENGLE_BYTES_MAX);
}
/**
* @brief Flash 槽 → 运行时槽(elapsed 清零)
*/
static void dengle_slot_from_flash(const DengleSlotFlash_t *src, DengleSlot_t *dst)
{
memset(dst, 0, sizeof(*dst));
dst->enable = src->enable;
dst->mode = src->mode;
dst->cmd_id = src->cmd_id;
dst->period_ms = src->period_ms;
dst->data_n = src->data_n;
dst->elapsed_ms = 0;
memcpy(dst->data.bytes, src->data, DENGLE_BYTES_MAX);
}
/**
* @brief 保存全部 Dengle 配置到 Flash(分两半写入,控制单条 VM 长度)
* @note 须在任务/定时器上下文调用,禁止在中断里调用
*/
static void dengle_flash_save(void)
{
int ret;
uint8_t i;
/* 前半:slot 0~4 */
memset(&s_flash_half, 0, sizeof(s_flash_half));
s_flash_half.magic = DENGLE_FLASH_MAGIC;
s_flash_half.ver = DENGLE_FLASH_VER;
for (i = 0; i < DENGLE_FLASH_HALF; i++) {
dengle_slot_to_flash(&s_slots[i], &s_flash_half.slots[i]);
}
ret = syscfg_write(CFG_USER_DENGLE_L, (u8 *)&s_flash_half, sizeof(s_flash_half));
if (ret <= 0) {
printf("dengle flash L write fail ret=%d\n", ret);
}
/* 后半:slot 5~9 */
memset(&s_flash_half, 0, sizeof(s_flash_half));
s_flash_half.magic = DENGLE_FLASH_MAGIC;
s_flash_half.ver = DENGLE_FLASH_VER;
for (i = 0; i < DENGLE_FLASH_HALF; i++) {
dengle_slot_to_flash(&s_slots[DENGLE_FLASH_HALF + i], &s_flash_half.slots[i]);
}
ret = syscfg_write(CFG_USER_DENGLE_H, (u8 *)&s_flash_half, sizeof(s_flash_half));
if (ret <= 0) {
printf("dengle flash H write fail ret=%d\n", ret);
} else {
printf("dengle flash saved, active=%u\n", dengle_sched_get_active_count());
}
}
/**
* @brief 延时落盘:先回 ACK,避免与组包发送叠在同一深调用栈
*/
static void dengle_flash_save_timeout(void *priv)
{
(void)priv;
s_save_timer = 0;
dengle_flash_save();
}
static void dengle_flash_save_defer(void)
{
if (s_save_timer) {
sys_timeout_del(s_save_timer);
s_save_timer = 0;
}
s_save_timer = sys_timeout_add(NULL, dengle_flash_save_timeout, 50);
}
/**
* @brief 从上电 Flash 恢复 Dengle 配置
*/
static void dengle_flash_load(void)
{
int ret;
uint8_t i;
/* 前半 */
memset(&s_flash_half, 0, sizeof(s_flash_half));
ret = syscfg_read(CFG_USER_DENGLE_L, (u8 *)&s_flash_half, sizeof(s_flash_half));
if (ret > 0 && s_flash_half.magic == DENGLE_FLASH_MAGIC &&
s_flash_half.ver == DENGLE_FLASH_VER) {
for (i = 0; i < DENGLE_FLASH_HALF; i++) {
dengle_slot_from_flash(&s_flash_half.slots[i], &s_slots[i]);
}
} else {
printf("dengle flash L empty/invalid ret=%d\n", ret);
}
/* 后半 */
memset(&s_flash_half, 0, sizeof(s_flash_half));
ret = syscfg_read(CFG_USER_DENGLE_H, (u8 *)&s_flash_half, sizeof(s_flash_half));
if (ret > 0 && s_flash_half.magic == DENGLE_FLASH_MAGIC &&
s_flash_half.ver == DENGLE_FLASH_VER) {
for (i = 0; i < DENGLE_FLASH_HALF; i++) {
dengle_slot_from_flash(&s_flash_half.slots[i],
&s_slots[DENGLE_FLASH_HALF + i]);
}
} else {
printf("dengle flash H empty/invalid ret=%d\n", ret);
}
printf("dengle flash loaded, active=%u\n", dengle_sched_get_active_count());
}
/*============================================================================*/
/* BLE 发送(两条路径) */
/*============================================================================*/
/**
* @brief CBCT/CBFDREPORTCMD + ycmd.arg_int32[]
* @note 对齐 usr_test_bleproto_runcmd 组包方式
*/
static void dengle_send_int32(const DengleSlot_t *slot)
{
bleproto_reportcmd_req_t *req;
int elen;
uint8_t i;
if (!slot || usr_get_conn_service() == 0) {
return;
}
memset(&s_encode_desc, 0, sizeof(s_encode_desc));
s_encode_desc.header.version = 0;
s_encode_desc.header.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON;
s_encode_desc.header.msgtype = BLEPROTO_APPDATA_MSGTYPE_REQ;
s_encode_desc.header.msgid = usr_ble_rx_msgid_get();
s_encode_desc.header.encrypt = 0;
s_encode_desc.header.serviceid = E_BLEPROTO_SERVICE_ID_REPORTCMD;
req = &s_encode_desc.datast.reportcmd_req;
req->ycmd.cmd_id = slot->cmd_id;
req->ycmd.arg_int32_count = slot->data_n;
req->ycmd.arg_string_count = 0;
req->ycmd.arg_bytes_count = 0;
for (i = 0; i < slot->data_n && i < DENGLE_INT_MAX; i++) {
req->ycmd.arg_int32[i] = slot->data.i32[i];
}
elen = bleproto_appdata_encode(s_txbuf, sizeof(s_txbuf), sizeof(s_txbuf), &s_encode_desc);
printf("dengle INT32 cmd_id=%u n=%u elen=%d\n", slot->cmd_id, slot->data_n, elen);
if (elen > 0) {
usr_ble_send_data(s_txbuf, (u16)elen);
}
}
/**
* @brief 其它产品:REPORTCMD_V2 + bytes_data
* @note 对齐 usr_test_protocol 组包方式
*/
static void dengle_send_bytes(const DengleSlot_t *slot)
{
ble_proto_packet_t *pkt;
int elen;
if (!slot || usr_get_conn_service() == 0) {
return;
}
memset(&s_encode_desc, 0, sizeof(s_encode_desc));
s_encode_desc.header.version = 0;
s_encode_desc.header.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON;
s_encode_desc.header.msgtype = BLEPROTO_APPDATA_MSGTYPE_REQ;
s_encode_desc.header.msgid = usr_ble_rx_msgid_get();
s_encode_desc.header.encrypt = 0;
s_encode_desc.header.serviceid = E_BLEPROTO_SERVICE_ID_REPORTCMD_V2;
pkt = &s_encode_desc.datast.reportcmd_v2_req;
pkt->cmd = slot->cmd_id;
pkt->reserved = 0;
pkt->gateway_int_cnt = 0;
pkt->device_int_len = 0;
pkt->device_str_len = 0;
pkt->device_bytes_len = slot->data_n;
pkt->bytes_data = slot->data.bytes;
elen = bleproto_appdata_encode(s_txbuf, sizeof(s_txbuf), sizeof(s_txbuf), &s_encode_desc);
printf("dengle BYTES cmd=%u n=%u elen=%d\n", slot->cmd_id, slot->data_n, elen);
if (elen > 0) {
usr_ble_send_data(s_txbuf, (u16)elen);
}
}
static void dengle_send_slot(const DengleSlot_t *slot)
{
if (!slot || !slot->enable || slot->data_n == 0) {
return;
}
/* USB 连着电脑时不发,避免配置阶段干扰 */
if (dengle_is_usb_pause()) {
return;
}
if (slot->mode == DENGLE_MODE_INT32) {
dengle_send_int32(slot);
} else {
dengle_send_bytes(slot);
}
}
/**
* @brief 延时立即发送:与 USB 解析/ACK 错开,降低栈峰值
*/
static void dengle_imm_send_timeout(void *priv)
{
uint8_t slot_id = (uint8_t)((u32)priv);
s_imm_send_timer = 0;
if (slot_id < DENGLE_SLOT_MAX) {
dengle_send_slot(&s_slots[slot_id]);
}
}
static void dengle_imm_send_defer(uint8_t slot_id)
{
s_imm_send_slot = slot_id;
if (s_imm_send_timer) {
sys_timeout_del(s_imm_send_timer);
s_imm_send_timer = 0;
}
s_imm_send_timer = sys_timeout_add((void *)((u32)slot_id),
dengle_imm_send_timeout, 30);
}
/*============================================================================*/
/* 定时节拍 */
/*============================================================================*/
static void dengle_tick(void *priv)
{
uint8_t i;
DengleSlot_t *slot;
(void)priv;
/* USB 在线:冻结计时,断开后从完整周期重新开始,避免拔线瞬间连发 */
if (dengle_is_usb_pause()) {
if (!s_usb_pause_logged) {
s_usb_pause_logged = 1;
printf("dengle pause: COM open\n");
}
for (i = 0; i < DENGLE_SLOT_MAX; i++) {
s_slots[i].elapsed_ms = 0;
}
return;
}
if (s_usb_pause_logged) {
s_usb_pause_logged = 0;
printf("dengle resume: COM closed\n");
}
for (i = 0; i < DENGLE_SLOT_MAX; i++) {
slot = &s_slots[i];
if (!slot->enable || slot->period_ms == 0) {
continue;
}
slot->elapsed_ms += DENGLE_TICK_MS;
if (slot->elapsed_ms >= slot->period_ms) {
slot->elapsed_ms = 0;
dengle_send_slot(slot);
}
}
}
/*============================================================================*/
/* 对外接口 */
/*============================================================================*/
Dengle_Ret_t dengle_sched_init(void)
{
memset(s_slots, 0, sizeof(s_slots));
dengle_flash_load();
s_inited = 1;
if (s_tick_timer == 0) {
s_tick_timer = sys_timer_add(NULL, dengle_tick, DENGLE_TICK_MS);
}
printf("dengle_sched_init ok\n");
return DENGLE_OK;
}
Dengle_Ret_t dengle_sched_clear_all(void)
{
if (!s_inited) {
return DENGLE_ERR_NOT_INIT;
}
memset(s_slots, 0, sizeof(s_slots));
dengle_flash_save_defer();
printf("dengle clear all\n");
return DENGLE_OK;
}
uint8_t dengle_sched_get_active_count(void)
{
uint8_t i;
uint8_t cnt = 0;
for (i = 0; i < DENGLE_SLOT_MAX; i++) {
if (s_slots[i].enable) {
cnt++;
}
}
return cnt;
}
Dengle_Ret_t dengle_sched_usb_set(const uint8_t *payload, uint16_t payload_len)
{
DengleSlot_t *slot;
DengleMode_t mode;
uint8_t slot_id;
uint8_t enable;
uint8_t data_n;
uint8_t i;
uint16_t need;
if (!s_inited) {
return DENGLE_ERR_NOT_INIT;
}
if (!payload || payload_len < 9) {
return DENGLE_ERR_PARAM;
}
slot_id = payload[0];
enable = payload[1];
if (slot_id >= DENGLE_SLOT_MAX) {
return DENGLE_ERR_SLOT;
}
slot = &s_slots[slot_id];
memset(slot, 0, sizeof(*slot));
/* 仅关闭该槽 */
if (enable == 0) {
dengle_flash_save_defer();
printf("dengle slot%u disabled\n", slot_id);
return DENGLE_OK;
}
mode = dengle_get_mode_by_prodcode();
data_n = payload[8];
if (mode == DENGLE_MODE_INT32) {
if (data_n == 0 || data_n > DENGLE_INT_MAX) {
return DENGLE_ERR_PARAM;
}
need = 9 + (uint16_t)data_n * 4;
if (payload_len < need) {
return DENGLE_ERR_PARAM;
}
for (i = 0; i < data_n; i++) {
slot->data.i32[i] = (int32_t)dengle_read_u32_be(&payload[9 + i * 4]);
}
} else {
if (data_n == 0 || data_n > DENGLE_BYTES_MAX) {
return DENGLE_ERR_PARAM;
}
need = 9 + data_n;
if (payload_len < need) {
return DENGLE_ERR_PARAM;
}
memcpy(slot->data.bytes, &payload[9], data_n);
}
slot->enable = 1;
slot->mode = (uint8_t)mode;
slot->period_ms = dengle_read_u32_be(&payload[2]);
slot->cmd_id = dengle_read_u16_be(&payload[6]);
slot->data_n = data_n;
slot->elapsed_ms = 0;
if (slot->period_ms < DENGLE_TICK_MS) {
slot->period_ms = DENGLE_TICK_MS;
}
printf("dengle set slot=%u mode=%u period=%ums cmd=%u n=%u\n",
slot_id, slot->mode, slot->period_ms, slot->cmd_id, slot->data_n);
/* 先 ACK,再延时落盘/发送,避免与组包叠栈导致复位 */
dengle_flash_save_defer();
dengle_imm_send_defer(slot_id);
return DENGLE_OK;
}
/*============================================================================*/
/* 查询导出(供 USB 0x74 / 0x75 */
/*============================================================================*/
static void dengle_write_u16_be(uint8_t *p, uint16_t v)
{
p[0] = (uint8_t)(v >> 8);
p[1] = (uint8_t)(v & 0xFF);
}
static void dengle_write_u32_be(uint8_t *p, uint32_t v)
{
p[0] = (uint8_t)(v >> 24);
p[1] = (uint8_t)(v >> 16);
p[2] = (uint8_t)(v >> 8);
p[3] = (uint8_t)(v & 0xFF);
}
/**
* @brief 打包单个槽位(与 0x70 设置 payload 同格式,便于上位机复用解析)
* enable=0 时仅输出 [slot][0]
* enable=1 时输出 [slot][1][period][cmd][data_n][data...]
* INT32 模式 data 仍按大端 int32 导出
*/
int dengle_sched_pack_slot(uint8_t slot_id, uint8_t *buf, uint16_t max_len)
{
const DengleSlot_t *slot;
uint16_t need;
uint8_t i;
if (!s_inited || !buf) {
return -1;
}
if (slot_id >= DENGLE_SLOT_MAX) {
return -1;
}
slot = &s_slots[slot_id];
if (!slot->enable) {
if (max_len < 2) {
return -1;
}
buf[0] = slot_id;
buf[1] = 0;
return 2;
}
if (slot->mode == DENGLE_MODE_INT32) {
need = 9 + (uint16_t)slot->data_n * 4;
} else {
need = 9 + slot->data_n;
}
if (max_len < need) {
return -1;
}
buf[0] = slot_id;
buf[1] = 1;
dengle_write_u32_be(&buf[2], slot->period_ms);
dengle_write_u16_be(&buf[6], slot->cmd_id);
buf[8] = slot->data_n;
if (slot->mode == DENGLE_MODE_INT32) {
for (i = 0; i < slot->data_n; i++) {
dengle_write_u32_be(&buf[9 + i * 4], (uint32_t)slot->data.i32[i]);
}
} else {
memcpy(&buf[9], slot->data.bytes, slot->data_n);
}
return (int)need;
}
int dengle_sched_pack_all(uint8_t *buf, uint16_t max_len)
{
uint16_t offset = 0;
uint8_t i;
int n;
if (!s_inited || !buf) {
return -1;
}
for (i = 0; i < DENGLE_SLOT_MAX; i++) {
n = dengle_sched_pack_slot(i, &buf[offset],
(uint16_t)(max_len - offset));
if (n <= 0) {
return -1;
}
offset = (uint16_t)(offset + n);
}
return (int)offset;
}
+88
View File
@@ -0,0 +1,88 @@
/******************************************************************************
* @file usr_dengle_sched.h
* @brief Dengle 参数定时下发:USB 配置最多 10 条,按周期经 BLE 发出
* @author cyWu <1917507415@qq.com>
* @date 2026.07.30
* @version V1.2.0
* @history
* - V1.0.0, 2026.07.30, cyWu, 首次发布
* - V1.1.0, 2026.07.30, cyWu, 增加 Flash 断电保存
* - V1.2.0, 2026.07.30, cyWu, USB 连接时暂停定时发送
* - V1.2.1, 2026.07.30, cyWu, 改为 COM(DTR) 开闭控制暂停/恢复
******************************************************************************/
#ifndef __USR_DENGLE_SCHED_H__
#define __USR_DENGLE_SCHED_H__
#include <stdint.h>
/*============================================================================*/
/* 宏定义 */
/*============================================================================*/
#define DENGLE_SLOT_MAX (10) /**< 最多定时条目数 */
#define DENGLE_INT_MAX (16) /**< CBCT/CBFD:最多 int32 个数 */
#define DENGLE_BYTES_MAX (64) /**< 其它产品:最多 bytes 长度 */
#define DENGLE_TICK_MS (100) /**< 调度节拍 */
/*============================================================================*/
/* 错误码 */
/*============================================================================*/
typedef enum {
DENGLE_OK = 0,
DENGLE_ERR_PARAM,
DENGLE_ERR_SLOT,
DENGLE_ERR_MODE,
DENGLE_ERR_NOT_INIT
} Dengle_Ret_t;
/*============================================================================*/
/* 外部接口 */
/*============================================================================*/
/**
* @brief 初始化 Dengle 定时模块(启动 100ms 节拍)
* @return Dengle_Ret_t
*/
Dengle_Ret_t dengle_sched_init(void);
/**
* @brief USB 设置一条定时任务
* @note payload 格式见 .c 文件头注释
* @param payload USB 帧 payload(不含 55AA/LEN/CMD/SN/CKSUM
* @param payload_len 长度
* @return Dengle_Ret_t
*/
Dengle_Ret_t dengle_sched_usb_set(const uint8_t *payload, uint16_t payload_len);
/**
* @brief 清除全部定时任务
* @return Dengle_Ret_t
*/
Dengle_Ret_t dengle_sched_clear_all(void);
/**
* @brief 打包单个槽位配置(格式与 0x70 设置 payload 一致)
* @param slot_id 槽位 0~9
* @param buf 输出缓冲
* @param max_len 缓冲最大长度
* @return >0 写入字节数;<=0 失败
*/
int dengle_sched_pack_slot(uint8_t slot_id, uint8_t *buf, uint16_t max_len);
/**
* @brief 打包全部槽位配置(连续拼接多个 0x70 风格记录)
* @param buf 输出缓冲
* @param max_len 缓冲最大长度
* @return >0 写入字节数;<=0 失败
*/
int dengle_sched_pack_all(uint8_t *buf, uint16_t max_len);
/**
* @brief 获取有效条目数(调试用)
* @return 已使能槽位数
*/
uint8_t dengle_sched_get_active_count(void);
#endif /* __USR_DENGLE_SCHED_H__ */
+39
View File
@@ -714,6 +714,45 @@ void usr_app_ota_init()
}
}
// void usr_test_bleproto_runcmd(void)
// {
// bleproto_appdata_desc_t encode_desc = {0};
// encode_desc.header.version = 0;
// encode_desc.header.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON;
// encode_desc.header.msgtype = BLEPROTO_APPDATA_MSGTYPE_REQ;
// encode_desc.header.msgid = 1;
// encode_desc.header.encrypt = 0;
// encode_desc.header.serviceid = E_BLEPROTO_SERVICE_ID_REPORTCMD;
// bleproto_reportcmd_req_t *pkt = &encode_desc.datast.reportcmd_req;
// /*
// > 告警上报 (*设备主动上报*)
// * 命令ID 120
// * 参数说明
// | 索引 | 类型 | 描述 | 取值 |
// | ---- | ----- | ---------- | ----------------------------------------------------- |
// | 0 | int32 | 告警事件id | 5000:硬件故障;5001:低电量报警; 5010:震动开机报警 |
// | 1 | int32 | UTC时间戳 | 事件触发UTCS时间戳单位秒 |
// */
// req->ycmd.cmd_id = 100;
// req->ycmd.arg_int32[0] = 5001; // 电量上报
// req->ycmd.arg_int32[1] = usr_var.usr_cureent_utc; // UTC时间戳
// req->ycmd.arg_int32_count = 2;
// req->ycmd.t = usr_var.usr_cureent_utc;
// int elen = bleproto_appdata_encode(txbuf, sizeof(txbuf), sizeof(txbuf), &encode_desc);
// printf("encode_len = %d\n", elen);
// if (elen > 0)
// {
// usr_ble_send_data(txbuf, elen);
// printf_buf(txbuf, elen);
// }
// }
void usr_test_protocol(void)
{
bleproto_appdata_desc_t encode_desc = {0};
+162 -4
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;
}
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);
+5 -1
View File
@@ -19,7 +19,11 @@
#define USR_PRODCODE_LEN (4)
#define USR_PCODE_LEN (6)
#define USR_JB_CMD_SET_PRODCODE (0x64) /**< USB 下发产品码命令 */
#define USR_JB_CMD_SET_PRODCODE (0x64) /**< USB 设置产品码ACK=0x65 */
#define USR_JB_CMD_GET_PRODCODE (0x66) /**< USB 查询产品码;RSP=0x67 */
#define USR_JB_CMD_DENGLE_SET (0x70) /**< USB 设置 Dengle 定时;ACK=0x71 */
#define USR_JB_CMD_DENGLE_CLR (0x72) /**< USB 清除全部 DengleACK=0x73 */
#define USR_JB_CMD_DENGLE_QRY (0x74) /**< USB 查询 Dengle 配置;RSP=0x75 */
/*============================================================================*/
/* 外部接口 */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
+30 -1
View File
@@ -614,6 +614,7 @@ obj/Release/apps/common/device/usb/device/cdc.o
-r=obj/Release/apps/common/device/usb/device/cdc.o,usb_alloc_ep_dmabuffer,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,free,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,cdc_release,pl
-r=obj/Release/apps/common/device/usb/device/cdc.o,cdc_is_com_open,pl
-r=obj/Release/apps/common/device/usb/device/cdc.o,usb_device2id,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,usb_set_setup_recv,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,usb_set_setup_phase,l
@@ -626,6 +627,7 @@ obj/Release/apps/common/device/usb/device/cdc.o
-r=obj/Release/apps/common/device/usb/device/cdc.o,config_asser,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,log_tag_const_e_USB,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,log_tag_const_d_USB,l
-r=obj/Release/apps/common/device/usb/device/cdc.o,log_tag_const_i_USB,l
obj/Release/apps/common/device/usb/device/descriptor.o
-r=obj/Release/apps/common/device/usb/device/descriptor.o,get_device_descriptor,pl
-r=obj/Release/apps/common/device/usb/device/descriptor.o,get_language_str,pl
@@ -1296,11 +1298,11 @@ obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp
obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,ble_update_get_ready_jump_flag,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,usr_ble_send_data,pl
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,printf,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,muti_make_set_adv_data,pl
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,ble_user_cmd_prepare,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,muti_make_set_adv_data_updata,pl
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,puts,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,printf,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,printf_buf,l
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,ble_get_scan_rsp_ptr,pl
-r=obj/Release/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.o,ble_get_adv_data_ptr,pl
@@ -1608,6 +1610,7 @@ obj/Release/apps/earphone/app_main.o
-r=obj/Release/apps/earphone/app_main.o,check_power_on_voltage,l
-r=obj/Release/apps/earphone/app_main.o,usr_read_device_sta,l
-r=obj/Release/apps/earphone/app_main.o,usr_prodcode_init,l
-r=obj/Release/apps/earphone/app_main.o,dengle_sched_init,l
-r=obj/Release/apps/earphone/app_main.o,usr_clear_pair_info_noreset,l
-r=obj/Release/apps/earphone/app_main.o,ui_manage_init,l
-r=obj/Release/apps/earphone/app_main.o,ui_update_status,l
@@ -3279,6 +3282,27 @@ obj/Release/apps/usr_le_code/thirdpart/mjson/mjson.o
-r=obj/Release/apps/usr_le_code/thirdpart/mjson/mjson.o,jsonrpc_ctx_init,pl
-r=obj/Release/apps/usr_le_code/thirdpart/mjson/mjson.o,jsonrpc_init,pl
-r=obj/Release/apps/usr_le_code/thirdpart/mjson/mjson.o,jsonrpc_default_context,pl
obj/Release/apps/usr_le_code/usr_dengle_sched.o
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_init,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,sys_timer_add,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,printf,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_clear_all,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_get_active_count,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_usb_set,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_pack_slot,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,dengle_sched_pack_all,pl
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,syscfg_read,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,cdc_is_com_open,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,usr_get_conn_service,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,usr_ble_rx_msgid_get,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,bleproto_appdata_encode,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,usr_ble_send_data,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,sys_timeout_del,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,sys_timeout_add,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,syscfg_write,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,usr_prodcode_get,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,memcmp,l
-r=obj/Release/apps/usr_le_code/usr_dengle_sched.o,puts,l
obj/Release/apps/usr_le_code/usr_le_adv.o
-r=obj/Release/apps/usr_le_code/usr_le_adv.o,usr_get_pair_info,pl
-r=obj/Release/apps/usr_le_code/usr_le_adv.o,syscfg_read,l
@@ -3375,8 +3399,13 @@ obj/Release/apps/usr_le_code/usr_usb_jb.o
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,usr_usb_jb_feed,pl
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,sys_timeout_add,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,printf_buf,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,dengle_sched_usb_set,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,dengle_sched_clear_all,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,memcmp,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,usr_goto_pair_mode,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,cdc_write_data,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,dengle_sched_pack_slot,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,dengle_sched_pack_all,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,usr_get_conn_service,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,bleproto_appdata_encode,l
-r=obj/Release/apps/usr_le_code/usr_usb_jb.o,usr_ble_send_data,l
+654 -650
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -144,6 +144,8 @@ u8 *syscfg_ptr_read(u16 item_id, u16 *len);
#define CFG_USER_PAIR_INFO 2
#define CFG_USER_TIM_FLAG 3
#define CFG_USER_PROD_INFO 28 /* ProdtCode + productCode */
#define CFG_USER_DENGLE_L 29 /* Dengle slots 0~4 */
#define CFG_USER_DENGLE_H 30 /* Dengle slots 5~9 */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.