0xchocolate 2 лет назад
Родитель
Сommit
956d14b74c

+ 15 - 20
ReadMe.md

@@ -1,35 +1,32 @@
-[![FAP Build](https://github.com/0xchocolate/flipperzero-esp-esp/actions/workflows/build.yml/badge.svg)](https://github.com/0xchocolate/flipperzero-esp-esp/actions/workflows/build.yml)
+# ESP Flasher app for Flipper Zero
 
-# Esp Esp companion app for Flipper Zero
-
-Requires a connected dev board running Esp FW. [See install instructions from UberGuidoZ here.](https://github.com/UberGuidoZ/Flipper/tree/main/Esp_DevBoard#esp-install-information)
+Requires a connected ESP chip.
 
 ## Get the app
 1. Make sure you're logged in with a github account (otherwise the downloads in step 2 won't work)
-2. Navigate to the [FAP Build](https://github.com/0xchocolate/flipperzero-esp-esp/actions/workflows/build.yml)
+2. Navigate to the [FAP Build](https://github.com/0xchocolate/flipperzero-esp-flasher/actions/workflows/build.yml)
    GitHub action workflow, and select the most recent run, scroll down to artifacts.
 3. The FAP is built for the `dev` and `release` channels of both official and unleashed
    firmware. Download the artifact corresponding to your firmware version.
-4. (Optional step to avoid confusion) Go to "Apps/GPIO" on the Flipper SD Card, delete any existing Esp app, on some firmwares there will be a `ESP32CAM_Esp.fap` or similar.
-5. Extract `esp32_esp_flasher.fap` from the ZIP file downloaded in step 3 to your Flipper Zero SD card, preferably under Apps/GPIO along with the rest of the GPIO apps. (If you're using qFlipper to transfer files you need to extract the content of the ZIP file to your computer before you drag it to qFlipper, as qFlipper does not support direct dragging from a ZIP file (at least on Windows)).
+4. Extract `esp_flasher.fap` from the ZIP file downloaded in step 3 to your Flipper Zero SD card, preferably under Apps/GPIO along with the rest of the GPIO apps. (If you're using qFlipper to transfer files you need to extract the content of the ZIP file to your computer before you drag it to qFlipper, as qFlipper does not support direct dragging from a ZIP file (at least on Windows)).
 
 From a local clone of this repo, you can also build the app yourself using ufbt.
 
-## In-app ESP32 flasher (WIP)
+## Using the app
 Guide by [@francis2054](https://github.com/francis2054)
 
-The app now contains a work-in-progress of an ESP32 flasher (close to the bottom of the esp menu). Use at your own risk. This hardcodes addresses for non-S3 ESP32 chips.
+Use at your own risk. This hardcodes addresses for ESP chips.
 
-To use this method:
-1. Make sure you follow the instructions for how to get the Esp app on your Flipper Zero, they can be found on the top of this page. Latest release needs to be downloaded and installed.
-2. Go to [Justcallmekoko's firmware page](https://github.com/justcallmekoko/ESP32Esp/wiki/update-firmware#using-spacehuhn-web-updater) and download all files necessary for the board you are flashing, most boards will want all 4 files but for the Esp Devboard you want to download these 3 files: `0x1000` (Bootloader), `0x8000` (partitions), `0x10000` (Firmware). The `Boot App` is not needed for the Esp Devboard with this method. The Firmware one will redirect you to the releases page where you'll need to pick the one relevant to the board you're flashing, if you are using the official Wi-Fi Devboard you want to pick the one ending in `_flipper_sd_serial.bin`. 
+Example of how to flash marauder using this app:
+1. Make sure you follow the instructions for how to get the ESP flasher app on your Flipper Zero, they can be found on the top of this page. Latest release needs to be downloaded and installed.
+2. Go to [Justcallmekoko's firmware page](https://github.com/justcallmekoko/ESP32Marauder/wiki/update-firmware#using-spacehuhn-web-updater) (or alternative ESP firmware) and download all files necessary for the board you are flashing, most boards will want all 4 files but for the Wi-Fi Devboard you want to download these 3 files: `0x1000` (Bootloader), `0x8000` (partitions), `0x10000` (Firmware). The `Boot App` is not needed for the Wi-Fi Devboard with this method. The Firmware one will redirect you to the releases page where you'll need to pick the one relevant to the board you're flashing, if you are using the official Wi-Fi Devboard you want to pick the one ending in `_flipper_sd_serial.bin`. 
 3. Place all files downloaded in step 2 in a new folder on your desktop, the name does not matter. Rename the `_flipper_sd_serial.bin` file you downloaded in step 2 to `Firmware.bin`.
-4. Now for transferring the files to the Flipper Zero, drag all the files from the folder on your desktop to the "Esp" folder inside "apps_data" folder on the Flipper Zero SD card. Preferred method to transfer these files is plugging the SD card into your computer with an adapter, but qFlipper works as well. Insert the Flipper Zero SD Card back into the Flipper before proceeding to the next step.
+4. Now for transferring the files to the Flipper Zero, drag all the files from the folder on your desktop to the "esp_flasher" folder inside "apps_data" folder on the Flipper Zero SD card. Preferred method to transfer these files is plugging the SD card into your computer with an adapter, but qFlipper works as well. Insert the Flipper Zero SD Card back into the Flipper before proceeding to the next step.
 5. Plug your Wi-Fi Devboard into the Flipper.
 6. Press and keep holding the boot button while you press the reset button once, release the boot button after 2 seconds.
-7. Open the Esp app on your Flipper Zero, it should be named "esp32_esp_flasher" and be located under Apps->GPIO from the main menu if you followed the instructions for how to install the app further up on this page. (You might get an API mismatch error if the Flipper firmware you are running doesn't match the files you've downloaded, you can try "Continue" anyway, otherwise the app needs to be rebuilt or you might need to update the firmware on your Flipper).
-8. Press the up arrow on the Flipper three times to get to "Reflash ESP32 (WIP)" and open it.
-9. For "Bootloader" scroll down in the list and select `esp32_esp.ino.bootloader.bin`, for "Paritition table" select `esp32_esp.ino.partitions.bin` and for "Firmware" select `Firmware.bin`.
+7. Open the ESP Flasher app on your Flipper Zero, it should be located under Apps->GPIO from the main menu if you followed the instructions for how to install the app further up on this page. (You might get an API mismatch error if the Flipper firmware you are running doesn't match the files you've downloaded, you can try "Continue" anyway, otherwise the app needs to be rebuilt or you might need to update the firmware on your Flipper).
+8. Select "Flash ESP".
+9. For "Bootloader" scroll down in the list and select `esp32_marauder.ino.bootloader.bin`, for "Paritition table" select `esp32_marauder.ino.partitions.bin` and for "Firmware" select `Firmware.bin`.
 10. Scroll down and click "[>] FLASH" and wait for it to complete. (If you get errors here, press back button once and repeat step 6 then try "[>] FLASH" again).
 11. Once it says "Done flashing" on the screen, restart the Flipper and you are done :)
 
@@ -39,14 +36,12 @@ This process will improve with future updates! :)
 
 ## Support
 
-For app feedback, bugs, and feature requests, please [create an issue here](https://github.com/0xchocolate/flipperzero-firmware-with-esp-esp-companion/issues).
+For app feedback, bugs, and feature requests, please [create an issue here](https://github.com/0xchocolate/flipperzero-esp-flasher/issues).
 
-You can find me (0xchocolate) on discord as @cococode#6011.
+You can find me (0xchocolate) on discord as @cococode.
 
 If you'd like to donate to the app development effort:  
 **ETH**: `0xf32A1F0CD6122C97d8953183E53cB889cc087C9b`  
 **BTC**: `bc1qtw7s25cwdkuaups22yna8sttfxn0usm2f35wc3`
 
-Find more info about Esp and support its developer (justcallmekoko aka WillStunForFood) here: https://github.com/justcallmekoko/ESP32Esp
-
 If you found the app preinstalled in a firmware release, consider supporting the maintainers!

+ 29 - 15
esp_flasher_worker.c

@@ -43,7 +43,7 @@ static esp_loader_error_t _flash_file(EspFlasherApp* app, char* filepath, uint32
     loader_port_debug_print("Start programming\n");
     uint64_t last_updated = size;
     while(size > 0) {
-        if ((last_updated - size) > 50000) {
+        if((last_updated - size) > 50000) {
             // inform user every 50k bytes
             // TODO: draw a progress bar next update
             snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size);
@@ -85,23 +85,33 @@ static void _flash_all_files(EspFlasherApp* app) {
     esp_loader_error_t err;
     const int num_steps = app->num_selected_flash_options;
 
-    #define NUM_FLASH_ITEMS 6
+#define NUM_FLASH_ITEMS 6
     FlashItem items[NUM_FLASH_ITEMS] = {
-        { SelectedFlashBoot, "bootloader", app->bin_file_path_boot, app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT },
-        { SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART },
-        { SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS },
-        { SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0 },
-        { SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP },
-        { SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0 },
+        {SelectedFlashBoot,
+         "bootloader",
+         app->bin_file_path_boot,
+         app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT},
+        {SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART},
+        {SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS},
+        {SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0},
+        {SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP},
+        {SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0},
         /* if you add more entries, update NUM_FLASH_ITEMS above! */
     };
 
     char user_msg[256];
 
     int current_step = 1;
-    for (FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) {
+    for(FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) {
         if(app->selected_flash_options[item->selected]) {
-            snprintf(user_msg, sizeof(user_msg), "Flashing %s (%d/%d) to address 0x%lx\n", item->description, current_step++, num_steps, item->addr);
+            snprintf(
+                user_msg,
+                sizeof(user_msg),
+                "Flashing %s (%d/%d) to address 0x%lx\n",
+                item->description,
+                current_step++,
+                num_steps,
+                item->addr);
             loader_port_debug_print(user_msg);
             err = _flash_file(app, item->path, item->addr);
             if(err) {
@@ -126,11 +136,15 @@ static int32_t esp_flasher_flash_bin(void* context) {
     err = esp_loader_connect(&connect_config);
     if(err != ESP_LOADER_SUCCESS) {
         char err_msg[256];
-        snprintf(err_msg, sizeof(err_msg), "Cannot connect to target. Error: %u\nMake sure the device is in bootloader/reflash mode, then try again.\n", err);
+        snprintf(
+            err_msg,
+            sizeof(err_msg),
+            "Cannot connect to target. Error: %u\nMake sure the device is in bootloader/reflash mode, then try again.\n",
+            err);
         loader_port_debug_print(err_msg);
     }
 
-    #if 0 // still getting packet drops with this
+#if 0 // still getting packet drops with this
     // higher BR
     if(!err) {
         loader_port_debug_print("Increasing speed for faster flash\n");
@@ -146,15 +160,15 @@ static int32_t esp_flasher_flash_bin(void* context) {
         }
         furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
     }
-    #endif
+#endif
 
     if(!err) {
         loader_port_debug_print("Connected\n");
         _flash_all_files(app);
-        #if 0
+#if 0
         loader_port_debug_print("Restoring transmission rate\n");
         furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
-        #endif
+#endif
         loader_port_debug_print("Done flashing. Please reset the board manually.\n");
     }
 

+ 5 - 5
esp_flasher_worker.h

@@ -5,12 +5,12 @@
 #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
 #include "esp_loader_io.h"
 
-#define ESP_ADDR_BOOT_S3   0x0
-#define ESP_ADDR_BOOT      0x1000
-#define ESP_ADDR_PART      0x8000
-#define ESP_ADDR_NVS       0x9000
+#define ESP_ADDR_BOOT_S3 0x0
+#define ESP_ADDR_BOOT 0x1000
+#define ESP_ADDR_PART 0x8000
+#define ESP_ADDR_NVS 0x9000
 #define ESP_ADDR_BOOT_APP0 0xE000
-#define ESP_ADDR_APP       0x10000
+#define ESP_ADDR_APP 0x10000
 
 void esp_flasher_worker_start_thread(EspFlasherApp* app);
 void esp_flasher_worker_stop_thread(EspFlasherApp* app);

+ 4 - 5
scenes/esp_flasher_scene_about.c

@@ -1,16 +1,15 @@
 #include "../esp_flasher_app_i.h"
 
-void esp_flasher_scene_about_widget_callback(
-    GuiButtonType result,
-    InputType type,
-    void* context) {
+void esp_flasher_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
     EspFlasherApp* app = context;
     if(type == InputTypeShort) {
         view_dispatcher_send_custom_event(app->view_dispatcher, result);
     }
 }
 
-#define ESP_FLASHER_APP_DESCRIPTION "\e#Information\nVersion: " ESP_FLASHER_APP_VERSION "\nDeveloped by: 0xchocolate\n(@cococode on discord) using espressif's esp-serial-flasher library\nGithub: TODO\n\n\e#Description\nApp to flash ESP chips from\nthe flipper (over UART) using\nbin files on the sd card.\nReset the chip into bootloader\nmode before flashing.\n\n Supported targets:\n- ESP32\n- ESP8266\n- ESP32-S2\n- ESP32-S3\n- ESP32-C3\n- ESP32-C2\n- ESP32-H2"
+#define ESP_FLASHER_APP_DESCRIPTION                     \
+    "\e#Information\nVersion: " ESP_FLASHER_APP_VERSION \
+    "\nDeveloped by: 0xchocolate\n(@cococode on discord) using espressif's esp-serial-flasher library\nGithub: https://github.com/0xchocolate/flipperzero-esp-flasher\n\n\e#Description\nApp to flash ESP chips from\nthe flipper (over UART) using\nbin files on the sd card.\nReset the chip into bootloader\nmode before flashing.\n\n Supported targets:\n- ESP32\n- ESP8266\n- ESP32-S2\n- ESP32-S3\n- ESP32-C3\n- ESP32-C2\n- ESP32-H2"
 
 void esp_flasher_scene_about_on_enter(void* context) {
     EspFlasherApp* app = context;

+ 78 - 40
scenes/esp_flasher_scene_browse.c

@@ -27,28 +27,31 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
     switch(index) {
     case SubmenuIndexS3Mode:
         // toggle S3 mode
-        app->selected_flash_options[SelectedFlashS3Mode] = !app->selected_flash_options[SelectedFlashS3Mode];
+        app->selected_flash_options[SelectedFlashS3Mode] =
+            !app->selected_flash_options[SelectedFlashS3Mode];
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexBoot:
-        app->selected_flash_options[SelectedFlashBoot] = !app->selected_flash_options[SelectedFlashBoot];
-        if (app->selected_flash_options[SelectedFlashBoot]) {
+        app->selected_flash_options[SelectedFlashBoot] =
+            !app->selected_flash_options[SelectedFlashBoot];
+        if(app->selected_flash_options[SelectedFlashBoot]) {
             if(dialog_file_browser_show(
-                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+                   app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
                 strncpy(
                     app->bin_file_path_boot,
                     furi_string_get_cstr(selected_filepath),
                     sizeof(app->bin_file_path_boot));
             }
         }
-        if (app->bin_file_path_boot[0] == '\0') {
+        if(app->bin_file_path_boot[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashBoot] = false;
         }
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexPart:
-        app->selected_flash_options[SelectedFlashPart] = !app->selected_flash_options[SelectedFlashPart];
+        app->selected_flash_options[SelectedFlashPart] =
+            !app->selected_flash_options[SelectedFlashPart];
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
@@ -56,14 +59,15 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_part));
         }
-        if (app->bin_file_path_part[0] == '\0') {
+        if(app->bin_file_path_part[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashPart] = false;
         }
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexNvs:
-        app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs];
+        app->selected_flash_options[SelectedFlashNvs] =
+            !app->selected_flash_options[SelectedFlashNvs];
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
@@ -71,14 +75,15 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_nvs));
         }
-        if (app->bin_file_path_nvs[0] == '\0') {
+        if(app->bin_file_path_nvs[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashNvs] = false;
         }
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexBootApp0:
-        app->selected_flash_options[SelectedFlashBootApp0] = !app->selected_flash_options[SelectedFlashBootApp0];
+        app->selected_flash_options[SelectedFlashBootApp0] =
+            !app->selected_flash_options[SelectedFlashBootApp0];
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
@@ -86,14 +91,15 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_boot_app0));
         }
-        if (app->bin_file_path_boot_app0[0] == '\0') {
+        if(app->bin_file_path_boot_app0[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashBootApp0] = false;
         }
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexApp:
-        app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp];
+        app->selected_flash_options[SelectedFlashApp] =
+            !app->selected_flash_options[SelectedFlashApp];
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
@@ -101,14 +107,15 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_app));
         }
-        if (app->bin_file_path_app[0] == '\0') {
+        if(app->bin_file_path_app[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashApp] = false;
         }
         view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
         break;
     case SubmenuIndexCustom:
-        app->selected_flash_options[SelectedFlashCustom] = !app->selected_flash_options[SelectedFlashCustom];
+        app->selected_flash_options[SelectedFlashCustom] =
+            !app->selected_flash_options[SelectedFlashCustom];
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
@@ -116,7 +123,7 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_custom));
         }
-        if (app->bin_file_path_custom[0] == '\0') {
+        if(app->bin_file_path_custom[0] == '\0') {
             // if user didn't select a file, leave unselected
             app->selected_flash_options[SelectedFlashCustom] = false;
         }
@@ -125,12 +132,14 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
     case SubmenuIndexFlash:
         // count how many options are selected
         app->num_selected_flash_options = 0;
-        for (bool* option = &app->selected_flash_options[SelectedFlashBoot]; option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; ++option) {
-            if (*option) {
+        for(bool* option = &app->selected_flash_options[SelectedFlashBoot];
+            option < &app->selected_flash_options[NUM_FLASH_OPTIONS];
+            ++option) {
+            if(*option) {
                 ++app->num_selected_flash_options;
             }
         }
-        if (app->num_selected_flash_options) {
+        if(app->num_selected_flash_options) {
             // only start next scene if at least one option is selected
             scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
         }
@@ -141,17 +150,17 @@ static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
     furi_string_free(predefined_filepath);
 }
 
-#define STR_SELECT         "[x]"
-#define STR_UNSELECT       "[ ]"
-#define STR_BOOT           "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")"
-#define STR_BOOT_S3        "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")"
-#define STR_PART           "Part Table (" TOSTRING(ESP_ADDR_PART) ")"
-#define STR_NVS            "NVS (" TOSTRING(ESP_ADDR_NVS) ")"
-#define STR_BOOT_APP0      "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")"
-#define STR_APP            "Firmware (" TOSTRING(ESP_ADDR_APP) ")"
-#define STR_CUSTOM         "Custom"
-#define STR_FLASH_S3       "[>] FLASH (ESP32-S3)"
-#define STR_FLASH          "[>] FLASH"
+#define STR_SELECT "[x]"
+#define STR_UNSELECT "[ ]"
+#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")"
+#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")"
+#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")"
+#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")"
+#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")"
+#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")"
+#define STR_CUSTOM "Custom"
+#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)"
+#define STR_FLASH "[>] FLASH"
 static void _refresh_submenu(EspFlasherApp* app) {
     Submenu* submenu = app->submenu;
 
@@ -159,16 +168,21 @@ static void _refresh_submenu(EspFlasherApp* app) {
 
     submenu_set_header(submenu, "Browse for files to flash");
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : "[ ] Select if using S3", SubmenuIndexS3Mode, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" :
+                                                           "[ ] Select if using S3",
+        SubmenuIndexS3Mode,
+        esp_flasher_scene_browse_callback,
+        app);
     const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT;
-    if (app->selected_flash_options[SelectedFlashS3Mode]) {
-        if (app->selected_flash_options[SelectedFlashBoot]) {
+    if(app->selected_flash_options[SelectedFlashS3Mode]) {
+        if(app->selected_flash_options[SelectedFlashBoot]) {
             strSelectBootloader = STR_SELECT " " STR_BOOT_S3;
         } else {
             strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3;
         }
     } else {
-        if (app->selected_flash_options[SelectedFlashBoot]) {
+        if(app->selected_flash_options[SelectedFlashBoot]) {
             strSelectBootloader = STR_SELECT " " STR_BOOT;
         } else {
             strSelectBootloader = STR_UNSELECT " " STR_BOOT;
@@ -177,18 +191,42 @@ static void _refresh_submenu(EspFlasherApp* app) {
     submenu_add_item(
         submenu, strSelectBootloader, SubmenuIndexBoot, esp_flasher_scene_browse_callback, app);
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : STR_UNSELECT " " STR_PART, SubmenuIndexPart, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART :
+                                                         STR_UNSELECT " " STR_PART,
+        SubmenuIndexPart,
+        esp_flasher_scene_browse_callback,
+        app);
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS :
+                                                        STR_UNSELECT " " STR_NVS,
+        SubmenuIndexNvs,
+        esp_flasher_scene_browse_callback,
+        app);
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : STR_UNSELECT " " STR_BOOT_APP0, SubmenuIndexBootApp0, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 :
+                                                             STR_UNSELECT " " STR_BOOT_APP0,
+        SubmenuIndexBootApp0,
+        esp_flasher_scene_browse_callback,
+        app);
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : STR_UNSELECT " " STR_APP, SubmenuIndexApp, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP :
+                                                        STR_UNSELECT " " STR_APP,
+        SubmenuIndexApp,
+        esp_flasher_scene_browse_callback,
+        app);
     // TODO: custom addr
     //submenu_add_item(
     //    submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, esp_flasher_scene_browse_callback, app);
     submenu_add_item(
-        submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, esp_flasher_scene_browse_callback, app);
+        submenu,
+        app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH,
+        SubmenuIndexFlash,
+        esp_flasher_scene_browse_callback,
+        app);
 
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneBrowse));
@@ -212,8 +250,8 @@ void esp_flasher_scene_browse_on_enter(void* context) {
 bool esp_flasher_scene_browse_on_event(void* context, SceneManagerEvent event) {
     EspFlasherApp* app = context;
     bool consumed = false;
-    if (event.type == SceneManagerEventTypeCustom) {
-        if (event.event == EspFlasherEventRefreshSubmenu) {
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == EspFlasherEventRefreshSubmenu) {
             _refresh_submenu(app);
             consumed = true;
         }

+ 10 - 2
scenes/esp_flasher_scene_start.c

@@ -18,9 +18,17 @@ void esp_flasher_scene_start_on_enter(void* context) {
     EspFlasherApp* app = context;
     Submenu* submenu = app->submenu;
     submenu_add_item(
-        submenu, "Flash ESP", SubmenuIndexEspFlasherFlash, esp_flasher_scene_start_submenu_callback, app);
+        submenu,
+        "Flash ESP",
+        SubmenuIndexEspFlasherFlash,
+        esp_flasher_scene_start_submenu_callback,
+        app);
     submenu_add_item(
-        submenu, "About", SubmenuIndexEspFlasherAbout, esp_flasher_scene_start_submenu_callback, app);
+        submenu,
+        "About",
+        SubmenuIndexEspFlasherAbout,
+        esp_flasher_scene_start_submenu_callback,
+        app);
 
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneStart));