//
|
// Created by Administrator on 2022/11/28.
|
//
|
|
#include <cstring>
|
#include "dfu.h"
|
#include "../defs.h"
|
#include "../jni_log.h"
|
|
#define DEBUG(fmt, args...) LOGD("<dfu> <%s>: " fmt, __func__, ##args)
|
|
Dfu::Dfu(SendDfuPtr fun, const uint8_t *data, int length) {
|
dfuTryCnt = 0;
|
dfuFileBitmap = new uint8_t [128];
|
memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap));
|
|
if (length > 0) {
|
dfuFile = new uint8_t[length];
|
dfuFileLength = length;
|
memcpy(dfuFile, data, length);
|
}
|
SendDfuFile = fun;
|
}
|
|
Dfu::~Dfu() {
|
delete []dfuFileBitmap;
|
if (dfuFile != nullptr) {
|
delete []dfuFile;
|
}
|
}
|
|
int Dfu::GoNextDfu(void)
|
{
|
int dfuFileSent = 0, currDfuBlockLength = 0;
|
|
if (dfuFileLength == 0 || dfuFile == NULL || SendDfuFile == nullptr || dfuCancel)
|
return DFU_END;
|
|
int row = 0, col = 0;
|
|
dfuFileSent = dfuFileLength;
|
|
for (row = 0; row < sizeof(dfuFileBitmap); ++row) {
|
for (col = 0; col < 8; ++col) {
|
if ((dfuFileBitmap[row] & BV(col)) == 0) {
|
DEBUG("ROW = %d COL = %d", row, col);
|
dfuFileSent = row * DFU_FILE_BLOCK_SIZE * 8 + col * DFU_FILE_BLOCK_SIZE;
|
goto GET_FILE_START;
|
}
|
}
|
}
|
|
GET_FILE_START:
|
currDfuBlockLength = (dfuFileLength - dfuFileSent > DFU_FILE_BLOCK_SIZE) ? DFU_FILE_BLOCK_SIZE : (dfuFileLength - dfuFileSent);
|
|
if (dfuFileSent >= dfuFileLength || currDfuBlockLength == 0) {
|
return DFU_END;
|
}
|
|
SendDfuFile(dfuFileLength, dfuFileSent, currDfuBlockLength, dfuFile + dfuFileSent);
|
|
if (dfuFileSent > 0 && dfuFileSent + currDfuBlockLength < dfuFileLength) {
|
dfuFileBitmap[row] |= BV(col);
|
}
|
|
if (dfuFileSent == 0 || dfuFileSent + currDfuBlockLength == dfuFileLength) {
|
dfuTryCnt++;
|
if (dfuTryCnt > DFU_MAX_TRY) {
|
return DFU_END;
|
}
|
DEBUG("GoNextDfuLater 3 sec...");
|
return DFU_LONG_WAIT;
|
}
|
return DFU_SHORT_WAIT;
|
}
|
|
void Dfu::RemoteAck(const uint8_t *data, int length)
|
{
|
DEBUG("ID_MC_AHP_DFU_RESP %d len %d", data[0], length);
|
|
if (data[0] == 0) {
|
// 第一包传输成功
|
dfuFileBitmap[0] |= 0x01;
|
} else if (data[0] == 10) {
|
// 升级完成
|
memset(dfuFileBitmap, 0xFF, sizeof(dfuFileBitmap));
|
} else if (data[0] == 11) {
|
// 放弃传输
|
dfuCancel = true;
|
} else if (data[0] == 12) {
|
// 全部重传
|
memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap));
|
} else if (data[0] == 13) {
|
// 部分重传,有后续字段
|
DEBUG("BITMAP %02X %02X %02X %02X %02X", data[1], data[2], data[3], data[4], data[5]);
|
|
int total = dfuFileLength / DFU_FILE_BLOCK_SIZE + ((dfuFileLength % DFU_FILE_BLOCK_SIZE)?1:0);
|
int a = 0, b = 0;
|
for (int i = 1; i < length; ++i) {
|
for (int j = 0; j < 8; ++j) {
|
if ((data[i] & BV(j))) b++;
|
a++;
|
if (a == total) {
|
i = length;
|
break;
|
}
|
}
|
}
|
|
DEBUG("BITMAP total %d succ %d", total, b);
|
|
//memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap));
|
memcpy(dfuFileBitmap, data + 1, length - 1);
|
|
if (total % 8) {
|
dfuFileBitmap[total/8] &= ~BV((total%8) - 1);
|
} else {
|
dfuFileBitmap[(total+7)/8 - 1] &= ~BV(7);
|
}
|
// dfuFileBitmap[total/8] &= ~BV(total%8);
|
}
|
|
std::unique_lock<std::mutex> lk(cv_mtx);
|
expired = true;
|
cv.notify_one();
|
}
|
|
void Dfu::Run(void)
|
{
|
while(true) {
|
std::unique_lock<std::mutex> lk(cv_mtx);
|
expired = false;
|
int status = GoNextDfu();
|
|
if (status == DFU_END) {
|
break;
|
}
|
|
if (cv.wait_for(lk, std::chrono::milliseconds(status == DFU_LONG_WAIT? 3000: 10), [this] { return expired == true; }) ==
|
false) {
|
// timeout
|
} else {
|
// cancel
|
dfuTryCnt = 0;
|
}
|
}
|
}
|