|
- static const char *TAG = "ota";
- #include <esp_log.h>
-
- #include <esp_ota_ops.h>
- #include <lwip/apps/tftp_server.h>
-
- #include <freertos/FreeRTOS.h>
- #include <freertos/task.h>
-
- #include <cstring>
-
- #include "ota.hpp"
-
-
- // TODO: Stick this somewhere useful?
- static void reboot_soon_task(void*) {
- int delay_s = 1;
- ESP_LOGI(TAG, "Rebooting in %d second%s",
- delay_s, delay_s == 1 ? "" : "s");
- vTaskDelay(pdMS_TO_TICKS(delay_s * 1000));
- esp_restart();
- }
-
- static void reboot_soon() {
- xTaskCreate(
- reboot_soon_task, "reboot_task",
- configMINIMAL_STACK_SIZE * 2, // TODO: Choose the best size
- NULL, 1, NULL
- );
- }
-
-
- class OTA_Session {
- public:
- OTA_Session() :
- part(esp_ota_get_next_update_partition(NULL)),
- ota(0), failed(false), total_written(0)
- {
- if (!part) {
- ESP_LOGE(TAG, "Could not find update partition");
- failed = true;
- return;
- }
-
- auto err = esp_ota_begin(part, OTA_SIZE_UNKNOWN, &ota);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "esp_ota_begin: %d", err);
- failed = true;
- return;
- }
- }
-
- ~OTA_Session() {
- if (failed) {
- ESP_LOGE(TAG, "Aborting OTA due to previous failure");
- esp_ota_abort(ota);
- return;
- }
-
- ESP_LOGI(TAG, "Finalizing OTA (%d bytes)", total_written);
- auto err = esp_ota_end(ota);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "esp_ota_end: %d", err);
- esp_ota_abort(ota);
- return;
- }
-
- ESP_LOGI(TAG, "Setting new boot partition");
- err = esp_ota_set_boot_partition(part);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "esp_ota_set_boot_partition: %d", err);
- return;
- }
-
- ESP_LOGI(TAG, "OTA Successful");
-
- reboot_soon();
- }
-
- bool write(const void *data, int len) {
- if (failed) return false;
- auto err = esp_ota_write(ota, data, len);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "esp_ota_write(%d): %d", len, err);
- failed = true;
- return false;
- }
- total_written += len;
- return true;
- }
-
- private:
- const esp_partition_t* part;
- esp_ota_handle_t ota;
- bool failed;
- int total_written;
- };
-
-
- static void* ota_open(const char *filename, const char *mode, u8_t write) {
- if (strcmp(mode, "octet") != 0) {
- ESP_LOGE(TAG, "Unexpected mode: %s", mode);
- return NULL;
- }
-
- if (strcmp(filename, "blinky.bin") != 0) {
- ESP_LOGE(TAG, "Unexpected filename: %s", mode);
- return NULL;
- }
-
- if (!write) {
- ESP_LOGE(TAG, "Illegal read attempt");
- return NULL;
- }
-
- ESP_LOGI(TAG, "Starting OTA");
-
- return new OTA_Session();
- }
-
- static void ota_close(void* handle) {
- OTA_Session *session = (OTA_Session*)handle;
- if (session) delete session;
- else ESP_LOGE(TAG, "Attempt to close invalid session");
- }
-
- static int ota_read(void* handle, void* buf, int len) {
- ESP_LOGE(TAG, "Super illegal read of %d bytes", len);
- return -1;
- }
-
- static int ota_write(void* handle, struct pbuf* p) {
- OTA_Session *session = (OTA_Session*)handle;
- if (!session) {
- ESP_LOGE(TAG, "Attempt to write to invalid session");
- return -1;
- }
-
- for (; p; p = p->next) {
- if (!session->write(p->payload, p->len)) {
- ESP_LOGE(TAG, "Failed to write %d bytes", p->len);
- return -1;
- }
- }
-
- return 0;
- }
-
-
- static tftp_context ota_context = {
- .open = ota_open,
- .close = ota_close,
- .read = ota_read,
- .write = ota_write
- };
-
- int start_ota_serv() {
- ESP_LOGI(TAG, "Starting OTA server");
-
- ESP_ERROR_CHECK(tftp_init(&ota_context));
-
- return 0;
- }
-
-
- int stop_ota_serv() {
- tftp_cleanup();
- return 0;
- }
|