A36 PCB1.1 软件工程整理

This commit is contained in:
2024-04-17 19:45:26 +08:00
commit 3401b91efc
3896 changed files with 4032291 additions and 0 deletions

View File

@ -0,0 +1,356 @@
/******************************************************************************
* Copyright (c) 20203, Freqchip
*
* All rights reserved.
*
*
*/
#include <stdio.h>
#include <string.h>
//#include <core_cm33.h>
#include "fr30xx.h"
#include "co_util.h"
#include "gap_api.h"
#include "gatt_api.h"
#include "FreeRTOS.h"
#include "timers.h"
#include "ota.h"
#include "ota_service.h"
/******************************************************************************
* MACROS (宏定义)
*/
/*****************************************************************************
* CONSTANTS (常量定义)
*/
#define PMU_REG_FLASH_VDD_CTRL 0xFB
/*****************************************************************************
* TYPEDEFS (类型定义)
*/
__PACKED_STRUCT ota_ongoing_t{
uint8_t type;
uint8_t start_flag;
uint8_t erase_flag;
uint8_t mac_addr[6];
};
__PACKED_STRUCT ota_file_version_t{
uint32_t otaboot_version;
uint32_t app_version;
uint32_t controller_version;
uint32_t dsp_version;
};
__PACKED_STRUCT file_info_t{
uint32_t file_version;
uint32_t file_storage_base;
uint32_t file_length;
uint32_t file_crc;
};
__PACKED_STRUCT ota_info_t{
uint8_t first_check_flag[4];
uint8_t file_type; //烧录文件中,所包含的文件类型
struct file_info_t boot_file_info;
struct file_info_t app_file_info;
struct file_info_t controller_file_info;
struct file_info_t dsp_file_info;
uint8_t controller_flag;
struct ota_ongoing_t ota_ongoing;
uint32_t rsv[10];
};
__PACKED_STRUCT firmware_version
{
uint32_t firmware_version;
} __attribute__((packed));
__PACKED_STRUCT storage_baseaddr
{
uint32_t baseaddr;
} __attribute__((packed));
__PACKED_STRUCT page_erase_rsp
{
uint32_t base_address;
} __attribute__((packed));
__PACKED_STRUCT write_mem_rsp
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT read_mem_rsp
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT write_data_rsp
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT read_data_rsp
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT ota_start_rsp
{
uint32_t ota_start;
} __attribute__((packed));
__PACKED_STRUCT ota_finish_rsp
{
uint32_t ota_finsih_state;
} __attribute__((packed));
__PACKED_STRUCT app_ota_rsp_hdr_t
{
uint8_t result;
uint8_t org_opcode;
uint16_t length;
__PACKED union
{
uint8_t nvds_type;
struct firmware_version version;
struct storage_baseaddr baseaddr;
struct page_erase_rsp page_erase;
struct write_mem_rsp write_mem;
struct read_mem_rsp read_mem;
struct write_data_rsp write_data;
struct read_data_rsp read_data;
struct ota_finish_rsp finsih_rsp;
struct ota_start_rsp ota_start;
} __attribute__((packed)) rsp;
} __attribute__((packed));
__PACKED_STRUCT page_erase_cmd
{
uint32_t base_address;
} __attribute__((packed));
__PACKED_STRUCT write_mem_cmd
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT read_mem_cmd
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT write_data_cmd
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT read_data_cmd
{
uint32_t base_address;
uint16_t length;
} __attribute__((packed));
__PACKED_STRUCT firmware_check
{
uint32_t firmware_length;
uint32_t CRC32_data;
} __attribute__((packed));
__PACKED_STRUCT app_ota_cmd_hdr_t
{
uint8_t opcode;
uint16_t length;
__PACKED union
{
struct page_erase_cmd page_erase;
struct write_mem_cmd write_mem;
struct read_mem_cmd read_mem;
struct write_data_cmd write_data;
struct read_data_cmd read_data;
struct firmware_check fir_crc_data;
} __attribute__((packed)) cmd;
} __attribute__((packed));
__PACKED_STRUCT otas_send_rsp
{
uint8_t conidx;
uint16_t length;
uint8_t *buffer;
};
/******************************************************************************
* LOCAL VARIABLES (局部变量)
*/
static struct ota_info_t * ota_info;
/******************************************************************************
* GLOBAL VARIABLES (全局变量)
*/
extern uint8_t ble_static_addr[6];
/******************************************************************************
* LOCAL FUNCTIONS (本地函数)
*/
/******************************************************************************
* EXTERN FUNCTIONS (外部函数)
*/
extern void wdt_rst_start(void);
void show_reg(uint8_t *buffer,uint16_t length)
{
for(int i = 0; i < length; i++)
{
printf("%02x ",buffer[i]);
}
printf("\r\n");
}
void ota_check_file_init(void)
{
ota_info = pvPortMalloc(sizeof(struct ota_info_t));
flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info);
}
void ota_deinit(void)
{
}
/*********************************************************************
* @fn app_otas_recv_data
*
* @brief Otas Data handler
*
*/
void app_otas_recv_data(uint8_t conidx,uint8_t *p_data,uint16_t len)
{
struct app_ota_cmd_hdr_t *cmd_hdr = (struct app_ota_cmd_hdr_t *)p_data;
struct app_ota_rsp_hdr_t *rsp_hdr;
uint16_t rsp_data_len = (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN);
switch(cmd_hdr->opcode)
{
case OTA_CMD_NVDS_TYPE:
rsp_data_len += 1;
break;
case OTA_CMD_GET_STR_BASE:
rsp_data_len += sizeof(struct storage_baseaddr);
break;
case OTA_CMD_READ_FW_VER:
rsp_data_len += sizeof(struct firmware_version);
break;
case OTA_CMD_PAGE_ERASE:
rsp_data_len += sizeof(struct page_erase_rsp);
break;
case OTA_CMD_WRITE_DATA:
rsp_data_len += sizeof(struct write_data_rsp);
break;
case OTA_CMD_READ_DATA:
rsp_data_len += sizeof(struct read_data_rsp);
break;
case OTA_CMD_WRITE_MEM:
rsp_data_len += sizeof(struct write_mem_rsp);
break;
case OTA_CMD_READ_MEM:
rsp_data_len += sizeof(struct read_mem_rsp);
break;
case OTA_CMD_START:
rsp_data_len += sizeof(struct ota_start_rsp);
break;
case OTA_CMD_NULL:
return;
}
struct otas_send_rsp *req = pvPortMalloc(sizeof(struct otas_send_rsp));
uint16_t base_length;
req->conidx = conidx;
req->length = rsp_data_len;
req->buffer = pvPortMalloc(rsp_data_len);
rsp_hdr = (struct app_ota_rsp_hdr_t *)&req->buffer[0];
rsp_hdr->result = OTA_RSP_SUCCESS;
rsp_hdr->org_opcode = cmd_hdr->opcode;
rsp_hdr->length = rsp_data_len - (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN);
switch(cmd_hdr->opcode)
{
case OTA_CMD_NVDS_TYPE:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_GET_STR_BASE:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_READ_FW_VER:
{
uint8_t type;
type = *(p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN));
switch(type)
{
case FILE_BOOT_LOADER:
rsp_hdr->rsp.version.firmware_version = ota_info->boot_file_info.file_version;
break;
case FILE_APP:
rsp_hdr->rsp.version.firmware_version = ota_info->app_file_info.file_version;
break;
case FILE_CONTROLLER:
rsp_hdr->rsp.version.firmware_version = ota_info->controller_file_info.file_version;
break;
case FILE_DSP:
rsp_hdr->rsp.version.firmware_version = ota_info->dsp_file_info.file_version;
break;
}
printf("version:%x",rsp_hdr->rsp.version.firmware_version);
}
break;
case OTA_CMD_PAGE_ERASE:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_CHIP_ERASE:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_WRITE_DATA:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_READ_DATA:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_WRITE_MEM:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_READ_MEM:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_REBOOT:
rsp_hdr->result = OTA_RSP_ERROR;
break;
case OTA_CMD_START:
{
uint8_t ota_type;
ota_type = *(p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN));
printf("ota type:%d\r\n",ota_type);
ota_info->ota_ongoing.type = ota_type;
ota_info->ota_ongoing.start_flag = 0x01;
ota_info->ota_ongoing.erase_flag = 0;
memcpy(ota_info->ota_ongoing.mac_addr,ble_static_addr,6);
flash_erase(QSPI0,OTA_BOOT_INFO_ADDRESS,0x1000);
flash_write(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info);
wdt_rst_start();
rsp_hdr->rsp.ota_start.ota_start = 0;
}
break;
default:
rsp_hdr->result = OTA_RSP_ERROR;
break;
}
ota_gatt_report_notify(conidx,req->buffer,req->length);
vPortFree(req->buffer);
vPortFree(req);
}

View File

@ -0,0 +1,78 @@
#ifndef OTA_H
#define OTA_H
#include <stdint.h>
#include <cmsis_armclang.h>
#define OTA_BOOT_INFO_ADDRESS 0x64000
#define OTA_B_STORAGE_ADDRESS 0x32000
#define APP_CODE_STORAGE_ADDRESS 0x66000
#define RETARGET_APP_CODE_ADDRESS 0x08066000 //APP地址
#define APP_CODE_INFO_OFFSET 0x148
#define IMGAE_INFO_SIZE 0x10
#define FILE_CODE_ADDRESS_OFFSET IMGAE_INFO_SIZE
#define FLASH_SIZE 0x400000 // 2M
#define DSP_SIZE (152*1024) // DSP SIZE 152k
#define CONTROLLER_SIZE (64*1024)
#define DSP_STORAGE_ADDRESS (FLASH_SIZE-DSP_SIZE)
#define CONTROLLER_STORAGE_ADDRESS (DSP_STORAGE_ADDRESS-CONTROLLER_SIZE)
#define DSP_START_ADDRESS (DSP_STORAGE_ADDRESS+FILE_CODE_ADDRESS_OFFSET)
#define CONTROLLER_START_ADDRESS (CONTROLLER_STORAGE_ADDRESS+FILE_CODE_ADDRESS_OFFSET)
#define OTA_HDR_RESULT_LEN 1
#define OTA_HDR_OPCODE_LEN 1
#define OTA_HDR_LENGTH_LEN 2
typedef enum
{
OTA_CMD_NVDS_TYPE,
OTA_CMD_GET_STR_BASE,
OTA_CMD_READ_FW_VER, //read firmware version
OTA_CMD_PAGE_ERASE,
OTA_CMD_CHIP_ERASE,
OTA_CMD_WRITE_DATA,
OTA_CMD_READ_DATA,
OTA_CMD_WRITE_MEM,
OTA_CMD_READ_MEM,
OTA_CMD_REBOOT,
OTA_CMD_START,
OTA_CMD_NULL,
} ota_cmd_t;
typedef enum
{
FILE_BOOT_LOADER =1,
FILE_APP,
FILE_CONTROLLER,
FILE_DSP,
}ota_file_type_t;
typedef enum
{
OTA_RSP_SUCCESS,
OTA_RSP_ERROR,
OTA_RSP_UNKNOWN_CMD,
}ota_rsp_t;
/*****************************************************************************
* TYPEDEFS (类型定义)
*/
struct app_otas_status_t
{
uint8_t read_opcode;
uint8_t length;
uint32_t base_addr;
};
__PACKED_STRUCT file_head_info_t{
uint8_t check[4];
uint32_t version;
uint32_t code_length;
uint32_t crc;
};
void app_otas_recv_data(uint8_t conidx,uint8_t *p_data,uint16_t len);
void ota_check_file_init(void);
#endif

View File

@ -0,0 +1,218 @@
/******************************************************************************
* Copyright (c) 20203, Freqchip
*
* All rights reserved.
*
*
*/
/******************************************************************************
* INCLUDES (包含头文件)
*/
#include <stdio.h>
#include <string.h>
#include "co_util.h"
#include "gap_api.h"
#include "gatt_api.h"
#include "FreeRTOS.h"
#include "timers.h"
#include "ota_service.h"
#include "ota.h"
/******************************************************************************
* MACROS (宏定义)
*/
/*****************************************************************************
* CONSTANTS (常量定义)
*/
/*****************************************************************************
* TYPEDEFS (类型定义)
*/
/******************************************************************************
* LOCAL VARIABLES (局部变量)
*/
static const uint8_t ota_svc_uuid[UUID_SIZE_16] = OTA_SVC_UUID;
static bool ota_link_ntf_enable = false;
static uint8_t ota_svc_id = 0;
/******************************************************************************
* GLOBAL VARIABLES (全局变量)
*/
/******************************************************************************
* Profile Attributes - Table
* 每一项都是一个attribute的定义。
* 第一个attribute为Service 的的定义。
* 每一个特征值(characteristic)的定义都至少包含三个attribute的定义
* 1. 特征值声明(Characteristic Declaration)
* 2. 特征值的值(Characteristic value)
* 3. 特征值描述符(Characteristic description)
* 如果有notification 或者indication 的功能则会包含四个attribute的定义除了前面定义的三个还会有一个特征值客户端配置(client characteristic configuration)。
*
*/
const gatt_attribute_t ota_svc_att_table[OTA_ATT_NB] =
{
// Update Over The AIR Service Declaration
[OTA_ATT_IDX_SERVICE] = { { UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) },
GATT_PROP_READ,UUID_SIZE_16, (uint8_t *)ota_svc_uuid
},
// OTA Information Characteristic Declaration
[OTA_ATT_IDX_CHAR_DECLARATION_VERSION_INFO] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ, 0, NULL
},
[OTA_ATT_IDX_CHAR_VALUE_VERSION_INFO]= { { UUID_SIZE_16, OTA_CHAR_UUID_VERSION_INFO },
GATT_PROP_READ, sizeof(uint16_t), NULL
},
// Notify Characteristic Declaration
[OTA_ATT_IDX_CHAR_DECLARATION_NOTI] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,0, NULL
},
[OTA_ATT_IDX_CHAR_VALUE_NOTI] = { { UUID_SIZE_16, OTA_CHAR_UUID_NOTI },
GATT_PROP_READ | GATT_PROP_NOTI, OTAS_NOTIFY_DATA_SIZE, NULL
},
[OTA_ATT_IDX_CHAR_CFG_NOTI] = { { UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ, 0,0
},
[OTA_IDX_CHAR_USER_DESCRIPTION_NOTI]= { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) },
GATT_PROP_READ, 12, NULL
},
// Tx Characteristic Declaration
[OTA_ATT_IDX_CHAR_DECLARATION_TX] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ, 0, NULL
},
[OTA_ATT_IDX_CHAR_VALUE_TX] = { { UUID_SIZE_16, OTA_CHAR_UUID_TX },
GATT_PROP_READ, OTAS_MAX_DATA_SIZE, NULL
},
// Rx Characteristic Declaration
[OTA_ATT_IDX_CHAR_DECLARATION_RX] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ, 0, NULL
},
[OTA_ATT_IDX_CHAR_VALUE_RX] = { { UUID_SIZE_16, OTA_CHAR_UUID_RX },
GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ, OTAS_MAX_DATA_SIZE, NULL
},
};
/*********************************************************************
* @fn ota_gatt_msg_handler
*
* @brief Ota Profile callback funtion for GATT messages. GATT read/write
* operations are handeled here.
*
* @param gatt_msg -GATT messages from GATT layer.
*
* @return None.
*/
static uint16_t ota_gatt_msg_handler(struct gatt_msg *p_msg)
{
switch(p_msg->msg_evt)
{
case GATTS_MSG_READ_REQ:
if(p_msg->att_idx == OTA_IDX_CHAR_USER_DESCRIPTION_NOTI)
{
memcpy(p_msg->param.gatt_data.p_msg_data, "OTA Response", strlen("OTA Response"));
return strlen("OTA Response");
}
else if (p_msg->att_idx == OTA_ATT_IDX_CHAR_VALUE_NOTI)
{
memcpy(p_msg->param.gatt_data.p_msg_data, "ntf_enable", strlen("ntf_enable"));
return strlen("ntf_enable");
}
else if (p_msg->att_idx == OTA_ATT_IDX_CHAR_VALUE_TX)
{
memcpy(p_msg->param.gatt_data.p_msg_data, "user_ota", strlen("user_ota"));
return strlen("user_ota");
}
else if (p_msg->att_idx == OTA_ATT_IDX_CHAR_VALUE_VERSION_INFO) //get version
{
memcpy(p_msg->param.gatt_data.p_msg_data, "\x00\x01", strlen("\x00\x01"));
return strlen("\x00\x01");
}
break;
case GATTS_MSG_WRITE_REQ:
if(p_msg->att_idx == OTA_ATT_IDX_CHAR_CFG_NOTI)
{
if(*(uint16_t *)p_msg->param.gatt_data.p_msg_data == 0x1)
{
printf("true\r\n");
ota_link_ntf_enable = true;
}
else
{
printf("false\r\n");
ota_link_ntf_enable = false;
}
}
else if(p_msg->att_idx == OTA_ATT_IDX_CHAR_VALUE_RX)
{
app_otas_recv_data(p_msg->conn_idx,p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len);
}
break;
case GATTC_MSG_CMP_EVT:
break;
case GATTC_MSG_LINK_CREATE:
break;
case GATTC_MSG_LINK_LOST:
ota_link_ntf_enable = false;
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn ota_gatt_report_notify
*
* @brief Send ota protocol response data.
*
*
* @param conidx - report idx of the hid_rpt_info array.
* p_data - data of the Ota information to be sent.
* len - length of the HID information data.
*
* @return none.
*/
void ota_gatt_report_notify(uint8_t conidx, uint8_t *p_data, uint16_t len)
{
if (ota_link_ntf_enable)
{
struct gatt_send_event ntf;
ntf.conidx = conidx;
ntf.svc_id = ota_svc_id;
ntf.att_idx = OTA_ATT_IDX_CHAR_VALUE_NOTI;
ntf.data_len = len;
ntf.p_data = p_data;
gatt_notification(&ntf);
}
}
/*********************************************************************
* @fn ota_gatt_add_service
*
* @brief Ota Profile add GATT service function.
* 添加GATT service到ATT的数据库里面。
*
* @param None.
*
*
* @return None.
*/
void ota_gatt_add_service(void)
{
gatt_service_t ota_profie_svc;
ota_profie_svc.p_att_tb = ota_svc_att_table;
ota_profie_svc.att_nb = OTA_ATT_NB;
ota_profie_svc.gatt_msg_handler = ota_gatt_msg_handler;
ota_svc_id = gatt_add_service(&ota_profie_svc);
ota_check_file_init();
}

View File

@ -0,0 +1,64 @@
#ifndef OTA_SERVICE_H
#define OTA_SERVICE_H
/*******************************************************************************
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
/*******************************************************************************
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define OTA_SVC_UUID {0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x02}
#define OTA_CHAR_UUID_TX {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x02}
#define OTA_CHAR_UUID_RX {0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x02}
#define OTA_CHAR_UUID_NOTI {0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x02}
#define OTA_CHAR_UUID_VERSION_INFO {0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x02}
#define OTAS_MAX_DATA_SIZE 600
#define OTAS_NOTIFY_DATA_SIZE 20
/*******************************************************************************
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
enum
{
OTA_ATT_IDX_SERVICE,
OTA_ATT_IDX_CHAR_DECLARATION_VERSION_INFO,
OTA_ATT_IDX_CHAR_VALUE_VERSION_INFO,
OTA_ATT_IDX_CHAR_DECLARATION_NOTI,
OTA_ATT_IDX_CHAR_VALUE_NOTI,
OTA_ATT_IDX_CHAR_CFG_NOTI,
OTA_IDX_CHAR_USER_DESCRIPTION_NOTI,
OTA_ATT_IDX_CHAR_DECLARATION_TX,
OTA_ATT_IDX_CHAR_VALUE_TX,
OTA_ATT_IDX_CHAR_DECLARATION_RX,
OTA_ATT_IDX_CHAR_VALUE_RX,
OTA_ATT_NB,
};
/*******************************************************************************
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*******************************************************************************
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*******************************************************************************
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*******************************************************************************
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
void ota_gatt_add_service(void);
void ota_gatt_report_notify(uint8_t conidx, uint8_t *p_data, uint16_t len);
#endif