mirror of https://github.com/arendst/Tasmota.git
Refactor RF Bridge fw upload
This commit is contained in:
parent
04c5212e4b
commit
d8678d149d
|
@ -35,15 +35,11 @@ const uint16_t CHUNKED_BUFFER_SIZE = (MESSZ / 2) - 100; // Chunk buffer size (s
|
|||
|
||||
const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds
|
||||
const uint16_t HTTP_RESTART_RECONNECT_TIME = 9000; // milliseconds - Allow time for restart and wifi reconnect
|
||||
const uint16_t HTTP_OTA_RESTART_RECONNECT_TIME = 20000; // milliseconds - Allow time for uploading binary, unzip/write to final destination and wifi reconnect
|
||||
const uint16_t HTTP_OTA_RESTART_RECONNECT_TIME = 24000; // milliseconds - Allow time for uploading binary, unzip/write to final destination and wifi reconnect
|
||||
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <DNSServer.h>
|
||||
|
||||
#ifdef USE_RF_FLASH
|
||||
uint8_t *efm8bb1_update = nullptr;
|
||||
#endif // USE_RF_FLASH
|
||||
|
||||
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTACLIENT, UPL_EFR32, UPL_SHD };
|
||||
|
||||
#ifdef USE_UNISHOX_COMPRESSION
|
||||
|
@ -792,11 +788,7 @@ const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG
|
|||
const char kEmulationOptions[] PROGMEM = D_NONE "|" D_BELKIN_WEMO "|" D_HUE_BRIDGE;
|
||||
|
||||
const char kUploadErrors[] PROGMEM =
|
||||
D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9
|
||||
#ifdef USE_RF_FLASH
|
||||
"|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13
|
||||
#endif
|
||||
;
|
||||
D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9;
|
||||
|
||||
const uint16_t DNS_PORT = 53;
|
||||
enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY};
|
||||
|
@ -2569,12 +2561,17 @@ void HandleInformation(void)
|
|||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE) || defined(USE_RF_FLASH)
|
||||
#define USE_WEB_FW_UPGRADE
|
||||
#endif
|
||||
|
||||
#ifdef USE_WEB_FW_UPGRADE
|
||||
|
||||
struct {
|
||||
size_t spi_hex_size;
|
||||
size_t spi_sector_counter;
|
||||
size_t spi_sector_cursor;
|
||||
bool active;
|
||||
bool ready;
|
||||
} BUpload;
|
||||
|
||||
|
@ -2582,12 +2579,13 @@ uint32_t BUploadStartSector(void) {
|
|||
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
|
||||
}
|
||||
|
||||
uint8_t BUploadInit(void) {
|
||||
void BUploadInit(uint32_t file_type) {
|
||||
Web.upload_file_type = file_type;
|
||||
BUpload.spi_hex_size = 0;
|
||||
BUpload.spi_sector_counter = BUploadStartSector();
|
||||
BUpload.spi_sector_cursor = 0;
|
||||
BUpload.active = true;
|
||||
BUpload.ready = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) {
|
||||
|
@ -2607,7 +2605,13 @@ uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_ZIGBEE_EZSP or USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE
|
||||
void BUploadDone(void) {
|
||||
Web.upload_file_type = UPL_TASMOTA;
|
||||
BUpload.active = false;
|
||||
BUpload.ready = false;
|
||||
}
|
||||
|
||||
#endif // USE_WEB_FW_UPGRADE
|
||||
|
||||
void HandleUpgradeFirmware(void)
|
||||
{
|
||||
|
@ -2660,7 +2664,7 @@ void HandleUploadDone(void)
|
|||
|
||||
#if defined(USE_ZIGBEE_EZSP)
|
||||
if ((UPL_EFR32 == Web.upload_file_type) && !Web.upload_error && BUpload.ready) {
|
||||
BUpload.ready = false; // Make sure not to follow thru again
|
||||
BUploadDone(); // Make sure not to follow thru again
|
||||
// GUI xmodem
|
||||
ZigbeeUploadStep1Done(BUploadStartSector(), BUpload.spi_hex_size);
|
||||
HandleZigbeeXfer();
|
||||
|
@ -2693,11 +2697,7 @@ void HandleUploadDone(void)
|
|||
WSContentSend_P(PSTR("<div style='text-align:center;'><b>" D_UPLOAD " <font color='#"));
|
||||
if (Web.upload_error) {
|
||||
WSContentSend_P(PSTR("%06x'>" D_FAILED "</font></b><br><br>"), WebColor(COL_TEXT_WARNING));
|
||||
#ifdef USE_RF_FLASH
|
||||
if (Web.upload_error < 15) {
|
||||
#else
|
||||
if (Web.upload_error < 10) {
|
||||
#endif
|
||||
GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors);
|
||||
} else {
|
||||
snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), Web.upload_error);
|
||||
|
@ -2709,7 +2709,7 @@ void HandleUploadDone(void)
|
|||
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
|
||||
TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update
|
||||
|
||||
#if defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
#if defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE) || defined(USE_RF_FLASH)
|
||||
if (BUpload.ready) {
|
||||
WSContentSend_P(PSTR("<br><div style='text-align:center;'><b>" D_TRANSFER_STARTED " ...</b></div>"));
|
||||
TasmotaGlobal.restart_flag = 0; // Hold restart as code still needs to be transferred to STM
|
||||
|
@ -2726,8 +2726,13 @@ void HandleUploadDone(void)
|
|||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
|
||||
#if defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
#ifdef USE_WEB_FW_UPGRADE
|
||||
if (BUpload.ready) {
|
||||
#ifdef USE_RF_FLASH
|
||||
if (UPL_EFM8BB1 == Web.upload_file_type) {
|
||||
SnfBrFlash(BUploadStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size);
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef SHELLY_FW_UPGRADE
|
||||
if (UPL_SHD == Web.upload_file_type) {
|
||||
ShdFlash(BUploadStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size);
|
||||
|
@ -2738,9 +2743,9 @@ void HandleUploadDone(void)
|
|||
TasmotaClient_Flash(BUploadStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size);
|
||||
}
|
||||
#endif
|
||||
BUploadDone();
|
||||
}
|
||||
#endif // USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE
|
||||
Web.upload_file_type = UPL_TASMOTA;
|
||||
#endif // USE_WEB_FW_UPGRADE
|
||||
}
|
||||
|
||||
void HandleUploadLoop(void)
|
||||
|
@ -2784,155 +2789,96 @@ void HandleUploadLoop(void)
|
|||
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
|
||||
MqttDisconnect();
|
||||
}
|
||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||
if (!Update.begin(maxSketchSpace)) { //start with max available size
|
||||
|
||||
// if (_serialoutput) Update.printError(Serial);
|
||||
// if (Update.getError() == UPDATE_ERROR_BOOTSTRAP) {
|
||||
// if (_serialoutput) Serial.println("Device still in UART update mode, perform powercycle");
|
||||
// }
|
||||
|
||||
Web.upload_error = 2; // Not enough space
|
||||
return;
|
||||
}
|
||||
}
|
||||
Web.upload_progress_dot_count = 0;
|
||||
}
|
||||
|
||||
// ***** Step2: Write upload file
|
||||
else if (!Web.upload_error && (UPLOAD_FILE_WRITE == upload.status)) {
|
||||
if (0 == upload.totalSize) {
|
||||
else if (UPLOAD_FILE_WRITE == upload.status) {
|
||||
if (0 == upload.totalSize) { // First block received
|
||||
if (UPL_SETTINGS == Web.upload_file_type) {
|
||||
Web.config_block_count = 0;
|
||||
}
|
||||
else {
|
||||
#ifdef USE_WEB_FW_UPGRADE
|
||||
#ifdef USE_RF_FLASH
|
||||
if ((SONOFF_BRIDGE == TasmotaGlobal.module_type) && (':' == upload.buf[0])) { // Check if this is a RF bridge FW file
|
||||
Update.end(); // End esp8266 update session
|
||||
Web.upload_file_type = UPL_EFM8BB1;
|
||||
|
||||
Web.upload_error = SnfBrUpdateInit(); // 10, 11
|
||||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
else if ((SONOFF_BRIDGE == TasmotaGlobal.module_type) && (':' == upload.buf[0])) { // Check if this is a RF bridge FW file
|
||||
BUploadInit(UPL_EFM8BB1);
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
#if defined(USE_ZIGBEE_EZSP)
|
||||
#ifdef USE_ZIGBEE_EZSP
|
||||
#ifdef ESP8266
|
||||
if ((SONOFF_ZB_BRIDGE == TasmotaGlobal.module_type) && (0xEB == upload.buf[0])) { // Check if this is a Zigbee bridge FW file
|
||||
else if ((SONOFF_ZB_BRIDGE == TasmotaGlobal.module_type) && (0xEB == upload.buf[0])) { // Check if this is a Zigbee bridge FW file
|
||||
#else // ESP32
|
||||
if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX) && (0xEB == upload.buf[0])) { // Check if this is a Zigbee bridge FW file
|
||||
else if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX) && (0xEB == upload.buf[0])) { // Check if this is a Zigbee bridge FW file
|
||||
#endif // ESP8266 or ESP32
|
||||
// Read complete file into ESP8266 flash
|
||||
// Current files are about 200k
|
||||
Web.upload_file_type = UPL_EFR32;
|
||||
|
||||
Web.upload_error = ZigbeeUploadStep1Init(); // 1
|
||||
if (Web.upload_error != 0) {
|
||||
Update.end(); // End esp8266 update session
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_TASMOTA_CLIENT)
|
||||
if (TasmotaClient_Available() && (':' == upload.buf[0])) { // Check if this is a ARDUINO CLIENT hex file
|
||||
Web.upload_file_type = UPL_TASMOTACLIENT;
|
||||
}
|
||||
#endif
|
||||
#if defined(SHELLY_FW_UPGRADE)
|
||||
if (ShdPresent() && (0x00 == upload.buf[0]) && (0x10 == upload.buf[1])) {
|
||||
Web.upload_file_type = UPL_SHD;
|
||||
}
|
||||
#endif
|
||||
if ((UPL_TASMOTACLIENT == Web.upload_file_type) || (UPL_SHD == Web.upload_file_type) || (UPL_EFR32 == Web.upload_file_type)) {
|
||||
Update.end(); // End esp8266 update session
|
||||
|
||||
Web.upload_error = BUploadInit();
|
||||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
#endif // USE_ZIGBEE_EZSP or USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE
|
||||
{
|
||||
if ((upload.buf[0] != 0xE9) && (upload.buf[0] != 0x1F)) { // 0x1F is gzipped 0xE9
|
||||
Web.upload_error = 3; // Magic byte is not 0xE9
|
||||
return;
|
||||
}
|
||||
if (0xE9 == upload.buf[0]) {
|
||||
uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4);
|
||||
if (bin_flash_size > ESP.getFlashChipRealSize()) {
|
||||
Web.upload_error = 4; // Program flash size is larger than real flash size
|
||||
return;
|
||||
}
|
||||
// upload.buf[2] = 3; // Force DOUT - ESP8285
|
||||
}
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "File type %d"), Web.upload_file_type);
|
||||
// Read complete file into ESP8266 flash
|
||||
// Current files are about 200k
|
||||
Web.upload_error = ZigbeeUploadStep1Init(); // 1
|
||||
if (Web.upload_error != 0) { return; }
|
||||
BUploadInit(UPL_EFR32);
|
||||
}
|
||||
}
|
||||
if (UPL_SETTINGS == Web.upload_file_type) {
|
||||
if (!Web.upload_error) {
|
||||
if (upload.currentSize > (sizeof(Settings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) {
|
||||
Web.upload_error = 9; // File too large
|
||||
return;
|
||||
}
|
||||
memcpy(settings_buffer + (Web.config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize);
|
||||
Web.config_block_count++;
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
else if (TasmotaClient_Available() && (':' == upload.buf[0])) { // Check if this is a ARDUINO CLIENT hex file
|
||||
BUploadInit(UPL_TASMOTACLIENT);
|
||||
}
|
||||
}
|
||||
#ifdef USE_RF_FLASH
|
||||
else if (UPL_EFM8BB1 == Web.upload_file_type) {
|
||||
if (efm8bb1_update != nullptr) { // We have carry over data since last write, i. e. a start but not an end
|
||||
ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize);
|
||||
free(efm8bb1_update);
|
||||
efm8bb1_update = nullptr;
|
||||
if (result != 0) {
|
||||
Web.upload_error = abs(result); // 2 = Not enough space, 8 = File invalid, 12, 13
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef SHELLY_FW_UPGRADE
|
||||
else if (ShdPresent() && (0x00 == upload.buf[0]) && (0x10 == upload.buf[1])) {
|
||||
BUploadInit(UPL_SHD);
|
||||
}
|
||||
ssize_t result = rf_search_and_write(upload.buf, upload.currentSize);
|
||||
if (result < 0) {
|
||||
Web.upload_error = abs(result); // 8, 12, 13
|
||||
#endif
|
||||
#endif // USE_WEB_FW_UPGRADE
|
||||
else if ((upload.buf[0] != 0xE9) && (upload.buf[0] != 0x1F)) { // 0x1F is gzipped 0xE9
|
||||
Web.upload_error = 3; // Invalid file signature - Magic byte is not 0xE9
|
||||
return;
|
||||
} else if (result > 0) {
|
||||
if ((size_t)result > upload.currentSize) {
|
||||
// Offset is larger than the buffer supplied, this should not happen
|
||||
Web.upload_error = 9; // File too large - Failed to decode RF firmware
|
||||
return;
|
||||
}
|
||||
// A remnant has been detected, allocate data for it plus a null termination byte
|
||||
size_t remnant_sz = upload.currentSize - result;
|
||||
efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1);
|
||||
if (efm8bb1_update == nullptr) {
|
||||
Web.upload_error = 2; // Not enough space - Unable to allocate memory to store new RF firmware
|
||||
return;
|
||||
}
|
||||
memcpy(efm8bb1_update, upload.buf + result, remnant_sz);
|
||||
// Add null termination at the end of of remnant buffer
|
||||
efm8bb1_update[remnant_sz] = '\0';
|
||||
}
|
||||
if (UPL_TASMOTA == Web.upload_file_type) {
|
||||
if (0xE9 == upload.buf[0]) {
|
||||
uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4);
|
||||
if (bin_flash_size > ESP.getFlashChipRealSize()) {
|
||||
Web.upload_error = 4; // Program flash size is larger than real flash size
|
||||
return;
|
||||
}
|
||||
// upload.buf[2] = 3; // Force DOUT - ESP8285
|
||||
}
|
||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||
if (!Update.begin(maxSketchSpace)) { //start with max available size
|
||||
Web.upload_error = 2; // Not enough space
|
||||
return;
|
||||
}
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "File type %d"), Web.upload_file_type);
|
||||
} // First block received
|
||||
|
||||
if (UPL_SETTINGS == Web.upload_file_type) {
|
||||
if (upload.currentSize > (sizeof(Settings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) {
|
||||
Web.upload_error = 9; // File too large
|
||||
return;
|
||||
}
|
||||
memcpy(settings_buffer + (Web.config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize);
|
||||
Web.config_block_count++;
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
else if ((UPL_EFR32 == Web.upload_file_type) || (UPL_TASMOTACLIENT == Web.upload_file_type) || (UPL_SHD == Web.upload_file_type)) {
|
||||
#ifdef USE_WEB_FW_UPGRADE
|
||||
else if (BUpload.active) {
|
||||
// Write a block
|
||||
Web.upload_error = BUploadWriteBuffer(upload.buf, upload.currentSize);
|
||||
if (Web.upload_error != 0) { return; }
|
||||
}
|
||||
#endif // USE_ZIGBEE_EZSP or USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE
|
||||
else { // firmware
|
||||
if (!Web.upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) {
|
||||
Web.upload_error = 5; // Upload buffer miscompare
|
||||
return;
|
||||
}
|
||||
if (_serialoutput) {
|
||||
Serial.printf(".");
|
||||
Web.upload_progress_dot_count++;
|
||||
if (!(Web.upload_progress_dot_count % 80)) { Serial.println(); }
|
||||
}
|
||||
#endif // USE_WEB_FW_UPGRADE
|
||||
else if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Web.upload_error = 5; // Upload buffer miscompare
|
||||
return;
|
||||
}
|
||||
if (_serialoutput) {
|
||||
Serial.printf(".");
|
||||
Web.upload_progress_dot_count++;
|
||||
if (!(Web.upload_progress_dot_count % 80)) { Serial.println(); }
|
||||
}
|
||||
}
|
||||
|
||||
// ***** Step3: Finish upload file
|
||||
else if(!Web.upload_error && (UPLOAD_FILE_END == upload.status)) {
|
||||
else if (UPLOAD_FILE_END == upload.status) {
|
||||
if (_serialoutput && (Web.upload_progress_dot_count % 80)) {
|
||||
Serial.println();
|
||||
}
|
||||
|
@ -2976,29 +2922,18 @@ void HandleUploadLoop(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#ifdef USE_RF_FLASH
|
||||
else if (UPL_EFM8BB1 == Web.upload_file_type) {
|
||||
// RF FW flash done
|
||||
// Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE)
|
||||
else if ((UPL_EFR32 == Web.upload_file_type) || (UPL_TASMOTACLIENT == Web.upload_file_type) || (UPL_SHD == Web.upload_file_type)) {
|
||||
#ifdef USE_WEB_FW_UPGRADE
|
||||
else if (BUpload.active) {
|
||||
// Done writing the hex to SPI flash
|
||||
BUpload.ready = true; // So we know on upload success page if it needs to flash hex or do a normal restart
|
||||
// Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif // USE_ZIGBEE_EZSP or USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE
|
||||
else {
|
||||
if (!Update.end(true)) { // true to set the size to the current progress
|
||||
if (_serialoutput) { Update.printError(Serial); }
|
||||
Web.upload_error = 6; // Upload failed. Enable logging 3
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Web.upload_error) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes"), upload.totalSize);
|
||||
#endif // USE_WEB_FW_UPGRADE
|
||||
else if (!Update.end(true)) { // true to set the size to the current progress
|
||||
if (_serialoutput) { Update.printError(Serial); }
|
||||
Web.upload_error = 6; // Upload failed. Enable logging 3
|
||||
return;
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes"), upload.totalSize);
|
||||
}
|
||||
|
||||
// ***** Step4: Abort upload file
|
||||
|
|
|
@ -58,68 +58,9 @@ struct SONOFFBRIDGE {
|
|||
#include "ihx.h"
|
||||
#include "c2.h"
|
||||
|
||||
const ssize_t RF_RECORD_NO_START_FOUND = -1;
|
||||
const ssize_t RF_RECORD_NO_END_FOUND = -2;
|
||||
|
||||
ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (buf[i] == ':') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return RF_RECORD_NO_START_FOUND;
|
||||
}
|
||||
|
||||
ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return RF_RECORD_NO_END_FOUND;
|
||||
}
|
||||
|
||||
ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len)
|
||||
{
|
||||
ssize_t record_start;
|
||||
ssize_t record_end;
|
||||
ssize_t glue_record_sz;
|
||||
uint8_t *glue_buf;
|
||||
ssize_t result;
|
||||
|
||||
if (remnant_data[0] != ':') { return -8; } // File invalid - RF Remnant data did not start with a start token
|
||||
|
||||
// Find end token in new data
|
||||
record_end = rf_find_hex_record_end(new_data, new_data_len);
|
||||
record_start = rf_find_hex_record_start(new_data, new_data_len);
|
||||
|
||||
// Be paranoid and check that there is no start marker before the end record
|
||||
// If so this implies that there was something wrong with the last start marker saved
|
||||
// in the last upload part
|
||||
if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) {
|
||||
return -8; // File invalid - Unexpected RF start marker found before RF end marker
|
||||
}
|
||||
|
||||
glue_record_sz = strlen((const char *) remnant_data) + record_end;
|
||||
|
||||
glue_buf = (uint8_t *) malloc(glue_record_sz);
|
||||
if (glue_buf == nullptr) { return -2; } // Not enough space
|
||||
|
||||
// Assemble new glue buffer
|
||||
memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data));
|
||||
memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end);
|
||||
|
||||
result = rf_decode_and_write(glue_buf, glue_record_sz);
|
||||
free(glue_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t rf_decode_and_write(uint8_t *record, size_t size)
|
||||
{
|
||||
uint32_t rf_decode_and_write(uint8_t *record, size_t size) {
|
||||
uint8_t err = ihx_decode(record, size);
|
||||
if (err != IHX_SUCCESS) { return -13; } // Failed to decode RF firmware
|
||||
if (err != IHX_SUCCESS) { return 13; } // Failed to decode RF firmware
|
||||
|
||||
ihx_t *h = (ihx_t *) record;
|
||||
if (h->record_type == IHX_RT_DATA) {
|
||||
|
@ -135,47 +76,49 @@ ssize_t rf_decode_and_write(uint8_t *record, size_t size)
|
|||
err = c2_reset();
|
||||
}
|
||||
|
||||
if (err != C2_SUCCESS) { return -12; } // Failed to write to RF chip
|
||||
if (err != C2_SUCCESS) { return 12; } // Failed to write to RF chip
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t rf_search_and_write(uint8_t *buf, size_t size)
|
||||
{
|
||||
uint32_t rf_search_and_write(uint8_t *data, size_t size) {
|
||||
// Binary contains a set of commands, decode and program each one
|
||||
ssize_t rec_end;
|
||||
ssize_t rec_start;
|
||||
ssize_t err;
|
||||
uint8_t buf[64];
|
||||
uint8_t* p_data = data;
|
||||
uint32_t addr = 0;
|
||||
uint32_t rec_end;
|
||||
uint32_t rec_start;
|
||||
uint32_t rec_size;
|
||||
uint32_t err;
|
||||
|
||||
while (addr < size) {
|
||||
memcpy(buf, p_data, sizeof(buf)); // Must load flash using memcpy on 4-byte boundary
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Find starts and ends of commands
|
||||
rec_start = rf_find_hex_record_start(buf + i, size - i);
|
||||
if (rec_start == RF_RECORD_NO_START_FOUND) {
|
||||
// There is nothing left to save in this buffer
|
||||
return -8; // File invalid
|
||||
for (rec_start = 0; rec_start < 8; rec_start++) {
|
||||
if (':' == buf[rec_start]) { break; }
|
||||
}
|
||||
|
||||
// Translate rec_start from local buffer position to chunk position
|
||||
rec_start += i;
|
||||
rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start);
|
||||
if (rec_end == RF_RECORD_NO_END_FOUND) {
|
||||
// We have found a start but not an end, save remnant
|
||||
return rec_start;
|
||||
if (rec_start > 7) { return 8; } // File invalid - RF Remnant data did not start with a start token
|
||||
for (rec_end = rec_start; rec_end < sizeof(buf); rec_end++) {
|
||||
if ('\n' == buf[rec_end]) { break; }
|
||||
}
|
||||
if (rec_end == sizeof(buf)) { return 9; } // File too large - Failed to decode RF firmware
|
||||
rec_size = rec_end - rec_start;
|
||||
|
||||
// Translate rec_end from local buffer position to chunk position
|
||||
rec_end += rec_start;
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buf + rec_start, rec_size);
|
||||
|
||||
err = rf_decode_and_write(buf + rec_start, rec_end - rec_start);
|
||||
if (err < 0) { return err; }
|
||||
i = rec_end;
|
||||
err = rf_decode_and_write(buf + rec_start, rec_size);
|
||||
if (err != 0) { return err; }
|
||||
|
||||
addr += rec_size +1;
|
||||
p_data += (rec_end & 0xFFFC); // Stay on 4-byte boundary
|
||||
delay(0);
|
||||
}
|
||||
// Buffer was perfectly aligned, start and end found without any remaining trailing characters
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t rf_erase_flash(void)
|
||||
{
|
||||
uint8_t rf_erase_flash(void) {
|
||||
uint8_t err;
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) { // HACK: Try multiple times as the command sometimes fails (unclear why)
|
||||
|
@ -197,12 +140,27 @@ uint8_t rf_erase_flash(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SnfBrUpdateInit(void)
|
||||
{
|
||||
uint32_t SnfBrUpdateFirmware(uint8_t* data, unsigned int size) {
|
||||
pinMode(PIN_C2CK, OUTPUT);
|
||||
pinMode(PIN_C2D, INPUT);
|
||||
|
||||
return rf_erase_flash(); // 10, 11
|
||||
uint32_t error = rf_erase_flash(); // 10, 11
|
||||
if (error) { return error; }
|
||||
|
||||
// AddLog_P(LOG_LEVEL_DEBUG, PSTR("RFB: Erased"));
|
||||
|
||||
return rf_search_and_write(data, size);
|
||||
}
|
||||
|
||||
void SnfBrFlash(uint32_t data, size_t size) {
|
||||
// uint32_t* values = (uint32_t*)(0x40200000 + data);
|
||||
// AddLog_P(LOG_LEVEL_DEBUG, PSTR("RFB: Flash 0x%08X"), values[0]);
|
||||
|
||||
uint32_t error = SnfBrUpdateFirmware((uint8_t*)(0x40200000 + data), size); // Allow flash access without ESP.flashRead
|
||||
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("RFB: FW flash state %d"), error);
|
||||
|
||||
TasmotaGlobal.restart_flag = 2; // Restart to re-init stopped services
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
|
||||
|
|
Loading…
Reference in New Issue