esp_flasher_scene_browse.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "../esp_flasher_app_i.h"
  2. #include "../esp_flasher_worker.h"
  3. enum SubmenuIndex {
  4. SubmenuIndexS3Mode,
  5. SubmenuIndexBoot,
  6. SubmenuIndexPart,
  7. SubmenuIndexNvs,
  8. SubmenuIndexBootApp0,
  9. SubmenuIndexApp,
  10. SubmenuIndexCustom,
  11. SubmenuIndexFlash,
  12. };
  13. static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
  14. EspFlasherApp* app = context;
  15. scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneBrowse, index);
  16. // browse for files
  17. FuriString* predefined_filepath = furi_string_alloc_set_str(ESP_APP_FOLDER);
  18. FuriString* selected_filepath = furi_string_alloc();
  19. DialogsFileBrowserOptions browser_options;
  20. dialog_file_browser_set_basic_options(&browser_options, ".bin", &I_Text_10x10);
  21. // TODO refactor
  22. switch(index) {
  23. case SubmenuIndexS3Mode:
  24. // toggle S3 mode
  25. app->selected_flash_options[SelectedFlashS3Mode] = !app->selected_flash_options[SelectedFlashS3Mode];
  26. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  27. break;
  28. case SubmenuIndexBoot:
  29. app->selected_flash_options[SelectedFlashBoot] = !app->selected_flash_options[SelectedFlashBoot];
  30. if (app->selected_flash_options[SelectedFlashBoot]) {
  31. if(dialog_file_browser_show(
  32. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  33. strncpy(
  34. app->bin_file_path_boot,
  35. furi_string_get_cstr(selected_filepath),
  36. sizeof(app->bin_file_path_boot));
  37. }
  38. }
  39. if (app->bin_file_path_boot[0] == '\0') {
  40. // if user didn't select a file, leave unselected
  41. app->selected_flash_options[SelectedFlashBoot] = false;
  42. }
  43. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  44. break;
  45. case SubmenuIndexPart:
  46. app->selected_flash_options[SelectedFlashPart] = !app->selected_flash_options[SelectedFlashPart];
  47. if(dialog_file_browser_show(
  48. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  49. strncpy(
  50. app->bin_file_path_part,
  51. furi_string_get_cstr(selected_filepath),
  52. sizeof(app->bin_file_path_part));
  53. }
  54. if (app->bin_file_path_part[0] == '\0') {
  55. // if user didn't select a file, leave unselected
  56. app->selected_flash_options[SelectedFlashPart] = false;
  57. }
  58. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  59. break;
  60. case SubmenuIndexNvs:
  61. app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs];
  62. if(dialog_file_browser_show(
  63. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  64. strncpy(
  65. app->bin_file_path_nvs,
  66. furi_string_get_cstr(selected_filepath),
  67. sizeof(app->bin_file_path_nvs));
  68. }
  69. if (app->bin_file_path_nvs[0] == '\0') {
  70. // if user didn't select a file, leave unselected
  71. app->selected_flash_options[SelectedFlashNvs] = false;
  72. }
  73. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  74. break;
  75. case SubmenuIndexBootApp0:
  76. app->selected_flash_options[SelectedFlashBootApp0] = !app->selected_flash_options[SelectedFlashBootApp0];
  77. if(dialog_file_browser_show(
  78. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  79. strncpy(
  80. app->bin_file_path_boot_app0,
  81. furi_string_get_cstr(selected_filepath),
  82. sizeof(app->bin_file_path_boot_app0));
  83. }
  84. if (app->bin_file_path_boot_app0[0] == '\0') {
  85. // if user didn't select a file, leave unselected
  86. app->selected_flash_options[SelectedFlashBootApp0] = false;
  87. }
  88. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  89. break;
  90. case SubmenuIndexApp:
  91. app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp];
  92. if(dialog_file_browser_show(
  93. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  94. strncpy(
  95. app->bin_file_path_app,
  96. furi_string_get_cstr(selected_filepath),
  97. sizeof(app->bin_file_path_app));
  98. }
  99. if (app->bin_file_path_app[0] == '\0') {
  100. // if user didn't select a file, leave unselected
  101. app->selected_flash_options[SelectedFlashApp] = false;
  102. }
  103. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  104. break;
  105. case SubmenuIndexCustom:
  106. app->selected_flash_options[SelectedFlashCustom] = !app->selected_flash_options[SelectedFlashCustom];
  107. if(dialog_file_browser_show(
  108. app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
  109. strncpy(
  110. app->bin_file_path_custom,
  111. furi_string_get_cstr(selected_filepath),
  112. sizeof(app->bin_file_path_custom));
  113. }
  114. if (app->bin_file_path_custom[0] == '\0') {
  115. // if user didn't select a file, leave unselected
  116. app->selected_flash_options[SelectedFlashCustom] = false;
  117. }
  118. view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
  119. break;
  120. case SubmenuIndexFlash:
  121. // count how many options are selected
  122. app->num_selected_flash_options = 0;
  123. for (bool* option = &app->selected_flash_options[SelectedFlashBoot]; option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; ++option) {
  124. if (*option) {
  125. ++app->num_selected_flash_options;
  126. }
  127. }
  128. if (app->num_selected_flash_options) {
  129. // only start next scene if at least one option is selected
  130. scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
  131. }
  132. break;
  133. }
  134. furi_string_free(selected_filepath);
  135. furi_string_free(predefined_filepath);
  136. }
  137. #define STR_SELECT "[x]"
  138. #define STR_UNSELECT "[ ]"
  139. #define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")"
  140. #define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")"
  141. #define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")"
  142. #define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")"
  143. #define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")"
  144. #define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")"
  145. #define STR_CUSTOM "Custom"
  146. #define STR_FLASH_S3 "[>] FLASH (ESP32-S3)"
  147. #define STR_FLASH "[>] FLASH"
  148. static void _refresh_submenu(EspFlasherApp* app) {
  149. Submenu* submenu = app->submenu;
  150. submenu_reset(app->submenu);
  151. submenu_set_header(submenu, "Browse for files to flash");
  152. submenu_add_item(
  153. submenu, app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : "[ ] Select if using S3", SubmenuIndexS3Mode, esp_flasher_scene_browse_callback, app);
  154. const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT;
  155. if (app->selected_flash_options[SelectedFlashS3Mode]) {
  156. if (app->selected_flash_options[SelectedFlashBoot]) {
  157. strSelectBootloader = STR_SELECT " " STR_BOOT_S3;
  158. } else {
  159. strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3;
  160. }
  161. } else {
  162. if (app->selected_flash_options[SelectedFlashBoot]) {
  163. strSelectBootloader = STR_SELECT " " STR_BOOT;
  164. } else {
  165. strSelectBootloader = STR_UNSELECT " " STR_BOOT;
  166. }
  167. }
  168. submenu_add_item(
  169. submenu, strSelectBootloader, SubmenuIndexBoot, esp_flasher_scene_browse_callback, app);
  170. submenu_add_item(
  171. submenu, app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : STR_UNSELECT " " STR_PART, SubmenuIndexPart, esp_flasher_scene_browse_callback, app);
  172. submenu_add_item(
  173. submenu, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, esp_flasher_scene_browse_callback, app);
  174. submenu_add_item(
  175. submenu, app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : STR_UNSELECT " " STR_BOOT_APP0, SubmenuIndexBootApp0, esp_flasher_scene_browse_callback, app);
  176. submenu_add_item(
  177. submenu, app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : STR_UNSELECT " " STR_APP, SubmenuIndexApp, esp_flasher_scene_browse_callback, app);
  178. // TODO: custom addr
  179. //submenu_add_item(
  180. // submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, esp_flasher_scene_browse_callback, app);
  181. submenu_add_item(
  182. submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, esp_flasher_scene_browse_callback, app);
  183. submenu_set_selected_item(
  184. submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneBrowse));
  185. view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewSubmenu);
  186. }
  187. void esp_flasher_scene_browse_on_enter(void* context) {
  188. EspFlasherApp* app = context;
  189. memset(app->selected_flash_options, 0, sizeof(app->selected_flash_options));
  190. app->bin_file_path_boot[0] = '\0';
  191. app->bin_file_path_part[0] = '\0';
  192. app->bin_file_path_nvs[0] = '\0';
  193. app->bin_file_path_boot_app0[0] = '\0';
  194. app->bin_file_path_app[0] = '\0';
  195. app->bin_file_path_custom[0] = '\0';
  196. _refresh_submenu(app);
  197. }
  198. bool esp_flasher_scene_browse_on_event(void* context, SceneManagerEvent event) {
  199. EspFlasherApp* app = context;
  200. bool consumed = false;
  201. if (event.type == SceneManagerEventTypeCustom) {
  202. if (event.event == EspFlasherEventRefreshSubmenu) {
  203. _refresh_submenu(app);
  204. consumed = true;
  205. }
  206. }
  207. return consumed;
  208. }
  209. void esp_flasher_scene_browse_on_exit(void* context) {
  210. EspFlasherApp* app = context;
  211. submenu_reset(app->submenu);
  212. }