mcu_hi3321_watch/tjd/ble/protocol/ble_file_trans_server.c
2025-05-26 20:15:20 +08:00

589 lines
20 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**************************************************************************************************
* Copyright (c) Fenda Technologies Co., Ltd. 2020-2021. All rights reserved.
* Description: 蓝牙文件传输协议
* Author: leon.sunzhen
* Create: 2020-12-23
************************************************************************************************/
#include "FreeRTOS.h"
#include "timers.h"
#include "am_util_debug.h"
#include "sys_config.h"
#include "ble_file_trans.h"
#include "ble_file_trans_server.h"
#include "amotas_api.h"
#include "amota_api.h"
#include "ble_management_server.h"
#include "ble_data_transmission.h"
#include "sys_memory.h"
#include "fs_api.h"
#define ENABLE_STATIC_PRINT true
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
#if ENABLE_STATIC_PRINT
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
#else
#define static_print_info(...)
#endif
const p_func_t FileTransServerFunc[FILE_TRANS_ACTION_MAX] = {
NULL,
BLE_FileTransFileInfo, //4.11.1
BLE_FileTransRequestCheck, //4.11.2
BLE_FileTransRequestData, //4.11.3
BLE_FileTransReturnData, //4.11.4
NULL, //4.11.5
NULL, //4.11.6
NULL, //4.11.7
NULL, //4.11.8
BLE_FileTransAllComplete, //4.11.9
NULL, //4.11.A
NULL, //4.11.B
NULL, //4.11.C
NULL, //4.11.D
NULL, //4.11.E
NULL, //4.11.F
NULL, //4.11.10
NULL, //4.11.11
NULL, //4.11.12
NULL, //4.11.13
NULL, //4.11.14
NULL, //4.11.15
BLE_FileTransAppGetInfo, //4.11.16
NULL, //4.11.17
BLE_FileTransAppRequestData, //4.11.18
NULL, //4.11.19
BLE_FileTransAppRcvComplete, //4.11.20
BLE_FileTransAppCancel, //4.11.21
};
//APP下发文件:
/*****************************************************************************
4.11.1 app发送文件信息
*****************************************************************************/
void BLE_FileTransFileInfo(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
protocol_data_info_t dataInfo = {0};
uint8_t fileId;
uint8_t version[32] = {0};
char fileName[128] = {0};
uint32_t fileSize;
uint8_t fileAction;
uint32_t fileCreateTime;
uint8_t model;
static_print_info("BLE_FileTransFileInfo\r\n");
if(inData == NULL || inLen == 0) {
return;
}
do {
user_get_data_info(&dataInfo, &inData, &inLen);
switch((dataInfo.type & 0x7F)) {
case FT_FILE_INFO_TYPE_FILE_ID:
fileId = *dataInfo.p_data;
static_print_info("fileId=%d\r\n", fileId);
break;
case FT_FILE_INFO_TYPE_VERSION:
memcpy(version, dataInfo.p_data, dataInfo.len);
version[31] = 0;
static_print_info("version=%s\r\n", version);
break;
case FT_FILE_INFO_TYPE_FILE_NAME:
memcpy(fileName, dataInfo.p_data, dataInfo.len);
fileName[127] = 0;
static_print_info("fileName=%s\r\n", fileName);
break;
case FT_FILE_INFO_TYPE_FILE_LENGTH:
if(dataInfo.len == 4) {
fileSize = (dataInfo.p_data[0] << 24) + \
(dataInfo.p_data[1] << 16) + \
(dataInfo.p_data[2] << 8) + \
dataInfo.p_data[3];
static_print_info("fileSize=%d\r\n", fileSize);
}
break;
case FT_FILE_INFO_TYPE_FILE_ACTION:
fileAction = *dataInfo.p_data;
static_print_info("fileAction=%d\r\n", fileAction);
break;
case FT_FILE_INFO_TYPE_FILE_CREATE_TIME:
if(dataInfo.len == 4) {
fileCreateTime = (dataInfo.p_data[0] << 24) + \
(dataInfo.p_data[1] << 16) + \
(dataInfo.p_data[2] << 8) + \
dataInfo.p_data[3];
static_print_info("fileCreateTime=%d\r\n", fileCreateTime);
}
break;
case FT_FILE_INFO_TYPE_MODEL:
model = *dataInfo.p_data;
static_print_info("model=%d\r\n", model);
break;
default:
break;
}
inData = dataInfo.p_data;
inData += (dataInfo.len);
inLen -= (2 + dataInfo.len);
if(inLen > FRAM_MAX_SIZ) {
inLen = 0;
}
} while(inLen);
file_trans_start(fileId, fileName, fileSize, (FileActionType)fileAction);
Ltv_t ltvArray[3] = {0};
FrameInfo_t frameInfo;
//回复
//file id
ltvArray[0].len = 3;
ltvArray[0].type = FT_FILE_INFO_TYPE_FILE_ID;
ltvArray[0].value = fileId;
ltvArray[1].len = 3;
ltvArray[1].type = FT_FILE_INFO_TYPE_MTU;
ltvArray[1].value = user_app_mtu_get();
ltvArray[2].len = 4;
ltvArray[2].type = FT_FILE_INFO_TYPE_FRAME;
ltvArray[2].value = 5000;
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_FILE_INFO;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 3);
vTaskDelay(50);
//请求CRC
ltvArray[0].len = 3;
ltvArray[0].type = FT_REQUEST_CHECK_TYPE_FILE_ID;
ltvArray[0].value = fileId;
ltvArray[1].len = 3;
ltvArray[1].type = FT_REQUEST_CHECK_TYPE_CHECK_TYPE;
ltvArray[1].value = 2; //请求crc
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_REQUEST_CHECK;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 2);
}
/*****************************************************************************
4.11.2 设备端请求文件校验值
*****************************************************************************/
void BLE_FileTransRequestCheck(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
protocol_data_info_t dataInfo = {0};
uint8_t checkType = 0;
static_print_info("BLE_FileTransRequestCheck\r\n");
if(inData == NULL || inLen == 0) {
return;
}
do {
user_get_data_info(&dataInfo, &inData, &inLen);
switch((dataInfo.type & 0x7F)) {
case FT_REQUEST_CHECK_TYPE_FILE_ID:
break;
case FT_REQUEST_CHECK_TYPE_CHECK_TYPE:
checkType = *dataInfo.p_data;
static_print_info("checkType=%d\r\n", checkType);
break;
case FT_REQUEST_CHECK_TYPE_CHECK_VALUE:
if(checkType == FT_CHECK_TYPE_CRC) {
uint32_t crc = *dataInfo.p_data;
FileTransSetCrc(crc);
} else if(checkType == FT_CHECK_TYPE_MD5) {
FileTransSetMd5(dataInfo.p_data);
}
break;
default:
break;
}
inData = dataInfo.p_data;
inData += (dataInfo.len);
inLen -= (2 + dataInfo.len);
if(inLen > FRAM_MAX_SIZ) {
inLen = 0;
}
} while(inLen);
BLE_SendFileTransRequestData();
}
/*****************************************************************************
4.11.3 设备请求一帧文件
*****************************************************************************/
void BLE_SendFileTransRequestData(void)
{
FileTransCtrlBlock_t ctrlBlock;
Ltv_t ltvArray[6] = {0};
FrameInfo_t frameInfo;
file_trans_get_ctrl_block(&ctrlBlock);
ltvArray[0].len = 3;
ltvArray[0].type = FT_REQUEST_DATA_TYPE_FILE_ID;
ltvArray[0].value = ctrlBlock.fileId;
ltvArray[1].len = 6;
ltvArray[1].type = FT_REQUEST_DATA_TYPE_OFFSET;
ltvArray[1].value = ctrlBlock.offset;
ltvArray[2].len = 6;
ltvArray[2].type = FT_REQUEST_DATA_TYPE_LENGTH;
ltvArray[2].value = ctrlBlock.nextPkgSize;
ltvArray[3].len = 4;
ltvArray[3].type = FT_REQUEST_DATA_TYPE_PSN;
ltvArray[3].value = ctrlBlock.psn;
ltvArray[4].len = 6;
ltvArray[4].type = FT_REQUEST_DATA_TYPE_FILE_SIZE;
ltvArray[4].value = ctrlBlock.fileSize;
ltvArray[5].len = 6;
ltvArray[5].type = FT_REQUEST_DATA_TYPE_FILE_RECEIVED;
ltvArray[5].value = ctrlBlock.offset;
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_REQUEST_DATA;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 6);
}
void BLE_FileTransRequestData(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
static_print_info("BLE_FileTransRequestData\r\n");
}
/*****************************************************************************
4.11.4 app传输一帧文件到设备
*****************************************************************************/
void BLE_FileTransReturnData(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
int32_t ret;
ret = file_trans_write_pkg(inData, inLen);
if (ret == FILE_WRITE_PKG_NO_REQUEST)
{//do nothing.
return;
}
if(ret > 0)
{
BLE_SendFileTransRequestData();
}
else if (ret == FILE_WRITE_PKG_COMPLETE)
{
BLE_FileTransComplete();
file_trans_succ();
}
else
{
amota_conn_param_update(CONN_PARAM_LOW_POWER);
vTaskDelay(10);
BLE_FileTransReportRcvState(-ret);
FileTransDisconn();
}
}
/*****************************************************************************
4.11.6 设备端回复文件接收完毕
*****************************************************************************/
void BLE_FileTransComplete(void)
{
static_print_info("BLE_FileTransComplete\r\n");
Ltv_t ltvArray[2] = {0};
FrameInfo_t frameInfo;
FileTransCtrlBlock_t ctrlBlock;
file_trans_get_ctrl_block(&ctrlBlock);
ltvArray[0].len = 3;
ltvArray[0].type = FT_RCV_COMPLETE_TYPE_FILE_ID;
ltvArray[0].value = ctrlBlock.fileId;
ltvArray[1].len = 3;
ltvArray[1].type = FT_REPORT_RCV_STATE_TYPE_ERROR_CODE;
ltvArray[1].value = 0;
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_RCV_COMPLETE;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 2);
}
/*****************************************************************************
4.11.7 设备端主动上报接收状态
*****************************************************************************/
void BLE_FileTransReportRcvState(uint16_t errCode)
{
static_print_info("BLE_FileTransReportRcvState\r\n");
Ltv_t ltvArray[2] = {0};
FrameInfo_t frameInfo;
FileTransCtrlBlock_t ctrlBlock;
file_trans_get_ctrl_block(&ctrlBlock);
ltvArray[0].len = 3;
ltvArray[0].type = FT_REPORT_RCV_STATE_TYPE_FILE_ID;
ltvArray[0].value = ctrlBlock.fileId;
ltvArray[1].len = 4;
ltvArray[1].type = FT_REPORT_RCV_STATE_TYPE_ERROR_CODE;
ltvArray[1].value = (BLE_FILE_TRANS_SERVER << 8) | errCode;
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_REPORT_RCV_STATE;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 2);
}
/*
static osThreadId_t UpdateFileTaskHandle = NULL;
static void UpdateFilesTask(void)
{
UpdateAllRcvFiles(false);
osThreadExit();
UpdateFileTaskHandle = NULL;
}
static void UpdateFilesTaskCreate(void)
{
const osThreadAttr_t attributes = {
.name = "updateFilesTask",
.priority = (osPriority_t)8,
.stack_size = 1024 * 10,
};
UpdateFileTaskHandle = osThreadNew((osThreadFunc_t)UpdateFilesTask, NULL, &attributes);
if(UpdateFileTaskHandle == NULL) {
PRINT_ERR("create update file task failed\n");
}
}
*/
/*****************************************************************************
4.11.9 APP告诉设备本轮逻辑的文件已传输完成
*****************************************************************************/
void BLE_FileTransAllComplete(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
static_print_info("\r\n BLE_FileTransAllComplete \r\n");
FileTransOver();
}
//APP请求文件:
static FileTransUploadFileInfo_t *g_pFileList = NULL;
static uint8_t g_uploadFileNum;
/*****************************************************************************
4.11.16 APP获取设备文件信息
*****************************************************************************/
void BLE_FileTransAppGetInfo(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
protocol_data_info_t dataInfo = {0};
uint8_t fileAction = 3; //默认为log文件
uint8_t fileTrans; //传输类型0-后台1-前台。暂不处理,目前上传都是后台
static_print_info("BLE_FileTransAppGetInfo\r\n");
if(inData == NULL || inLen == 0) {
return;
}
do {
user_get_data_info(&dataInfo, &inData, &inLen);
switch((dataInfo.type & 0x7F)) {
case FT_UPLOAD_FILE_INFO_TYPE_GET_FILE:
fileAction = *dataInfo.p_data;
static_print_info("fileAction=%d\r\n", fileAction);
break;
case FT_UPLOAD_FILE_INFO_TYPE_TRANS:
fileTrans = *dataInfo.p_data;
static_print_info("fileTrans=%d\r\n", fileTrans);
break;
default:
break;
}
inData = dataInfo.p_data;
inData += (dataInfo.len);
inLen -= (2 + dataInfo.len);
if(inLen > FRAM_MAX_SIZ) {
inLen = 0;
}
} while(inLen);
//1. 根据fileAction遍历文件存放在g_pFileList内g_pFileList的生命周期为下一次遍历之前
if(g_pFileList) {
vPortFree(g_pFileList);
}
g_uploadFileNum = GetFileListByAction((FileActionType)fileAction, &g_pFileList);
static_print_info("upload file num=%d\r\n", g_uploadFileNum);
if(g_pFileList == NULL) {
static_print_info("GetFileListByAction failed\r\n");
return;
}
//2. 根据遍历的文件大小malloc出ltvArray
Ltv_t *ltvArray = pvPortMalloc(sizeof(Ltv_t) * (5 * g_uploadFileNum + 1));
if(ltvArray == NULL) {
static_print_info("EXT_MALLOC failed\r\n");
return;
}
memset(ltvArray, 0, sizeof(Ltv_t) * (5 * g_uploadFileNum + 1));
//3. 填充ltvArray并发送
uint32_t fileListSize;
ltvArray[0].len = 3;
ltvArray[0].type = FT_UPLOAD_FILE_INFO_TYPE_FILES;
ltvArray[0].value = g_uploadFileNum;
for(uint32_t i = 0; i < g_uploadFileNum; i++) {
fileListSize = 0;
//file name
ltvArray[i * 5 + 2].len = strlen(g_pFileList[i].filePathName) + 2; // 因为传输同名文件APP会覆盖修改为传输路径
ltvArray[i * 5 + 2].type = FT_UPLOAD_FILE_INFO_TYPE_FILE_NAME;
ltvArray[i * 5 + 2].pValue = (uint8_t *)g_pFileList[i].filePathName;
fileListSize += ltvArray[i * 5 + 2].len;
//file size
ltvArray[i * 5 + 3].len = 6;
ltvArray[i * 5 + 3].type = FT_UPLOAD_FILE_INFO_TYPE_FILE_LENGTH;
ltvArray[i * 5 + 3].value = g_pFileList[i].fileSize;
fileListSize += ltvArray[i * 5 + 3].len;
//file frames
ltvArray[i * 5 + 4].len = 4;
ltvArray[i * 5 + 4].type = FT_UPLOAD_FILE_INFO_TYPE_FILE_FRAMES;
ltvArray[i * 5 + 4].value = g_pFileList[i].fileFrames;
fileListSize += ltvArray[i * 5 + 4].len;
//file id
ltvArray[i * 5 + 5].len = 3;
ltvArray[i * 5 + 5].type = FT_UPLOAD_FILE_INFO_TYPE_FILE_ID;
ltvArray[i * 5 + 5].value = g_pFileList[i].fileId;
fileListSize += ltvArray[i * 5 + 5].len;
//file list
ltvArray[i * 5 + 1].len = 3;
ltvArray[i * 5 + 1].type = FT_UPLOAD_FILE_INFO_TYPE_FILE_LIST;
ltvArray[i * 5 + 1].value = fileListSize;
}
FrameInfo_t frameInfo;
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_APP_GET_INFO;
frameInfo.frameType.value = 0;
BLE_SendLtvArray(&frameInfo, ltvArray, 5 * g_uploadFileNum + 1);
vPortFree(ltvArray);
}
/*****************************************************************************
4.11.18 APP通过文件信息请求一帧数据
*****************************************************************************/
void BLE_FileTransAppRequestData(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
protocol_data_info_t dataInfo = {0};
uint8_t fileId;
uint16_t receivedFrame;
uint16_t frame = 0;
FrameInfo_t frameInfo;
static_print_info("BLE_FileTransAppRequestData\r\n");
if(inData == NULL || inLen == 0) {
return;
}
do {
user_get_data_info(&dataInfo, &inData, &inLen);
switch((dataInfo.type & 0x7F)) {
case FT_UPLOAD_REQUEST_DATA_FILE_ID:
fileId = *dataInfo.p_data;
static_print_info("fileId=%d\r\n", fileId);
break;
case FT_UPLOAD_REQUEST_DATA_FILE_RECEIVED_FRAME:
receivedFrame = (dataInfo.p_data[0] << 8) + dataInfo.p_data[1];
static_print_info("receivedFrame=%d\r\n", receivedFrame);
break;
case FT_UPLOAD_REQUEST_DATA_FILE_FRAME:
frame = (dataInfo.p_data[0] << 8) + dataInfo.p_data[1];
static_print_info("frame=%d\r\n", frame);
break;
default:
break;
}
inData = dataInfo.p_data;
inData += (dataInfo.len);
inLen -= (2 + dataInfo.len);
if(inLen > FRAM_MAX_SIZ) {
inLen = 0;
}
} while(inLen);
if(g_pFileList == NULL) {
static_print_info("file list does not exist!\r\n");
return;
}
if(fileId >= g_uploadFileNum) {
static_print_info("fileId err,fileId=%d,g_uploadFileNum=%d\r\n", fileId, g_uploadFileNum);
return;
}
uint32_t offset = frame * FILE_UPLOAD_FRAME_SIZE;
uint8_t *readData = pvPortMalloc(FILE_UPLOAD_FRAME_SIZE + 3);
if(readData == NULL) {
static_print_info("readData malloc failed\r\n");
return;
}
readData[0] = fileId;
readData[1] = frame << 8;
readData[2] = frame;
int ret = fs_api_file_load(g_pFileList[fileId].filePathName, offset, readData + 3, FILE_UPLOAD_FRAME_SIZE);
if(ret > 0) {
frameInfo.serviceId = BLE_FILE_TRANS_SERVER;
frameInfo.commandId = FILE_TRANS_APP_RETURN_DATA; //回复4.11.19
frameInfo.frameType.value = 0;
BLE_SendFrame(&frameInfo, readData, ret + 3);
#if 0
/* 若是log文件则同步完成后删除 */
if(strncmp(g_pFileList[fileId].filePathName, DIR_DATA_LOG, strlen(DIR_DATA_LOG)) == 0) {
if(g_pFileList[fileId].fileFrames == frame + 1) {
static_print_info("get full frame\r\n");
fs_api_unlink(g_pFileList[fileId].filePathName);
}
}
#endif
} else {
static_print_info("FSFileLoad err,ret=%d\r\n", ret);
}
vPortFree(readData);
}
/*****************************************************************************
4.11.20 APP通知设备已接收完一个文件
*****************************************************************************/
void BLE_FileTransAppRcvComplete(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
//设备端不做处理
static_print_info("BLE_FileTransAppRcvComplete\r\n");
}
/*****************************************************************************
4.11.21 APP取消传输
*****************************************************************************/
void BLE_FileTransAppCancel(uint8_t *inData, uint16_t inLen, uint8_t *outData, uint16_t *outLen)
{
//设备端不做处理
static_print_info("BLE_FileTransAppCancel\r\n");
}