diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 4780da184..5e4606ca4 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -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 #include -#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("
" D_UPLOAD " " D_FAILED "

"), 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 "
"), 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("
" D_TRANSFER_STARTED " ...
")); 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 diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino index b7516fd2b..684698cb0 100644 --- a/tasmota/xdrv_06_snfbridge.ino +++ b/tasmota/xdrv_06_snfbridge.ino @@ -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