// // Created by Administrator on 2022/11/28. // #include #include "dfu.h" #include "../defs.h" #include "../jni_log.h" #define DEBUG(fmt, args...) LOGD(" <%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 lk(cv_mtx); expired = true; cv.notify_one(); } void Dfu::Run(void) { while(true) { std::unique_lock 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; } } }