spi_mem_view_progress.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "spi_mem_view_progress.h"
  2. #include <gui/elements.h>
  3. struct SPIMemProgressView {
  4. View* view;
  5. SPIMemProgressViewCallback callback;
  6. void* cb_ctx;
  7. };
  8. typedef enum {
  9. SPIMemProgressViewTypeRead,
  10. SPIMemProgressViewTypeVerify,
  11. SPIMemProgressViewTypeWrite,
  12. SPIMemProgressViewTypeUnknown
  13. } SPIMemProgressViewType;
  14. typedef struct {
  15. size_t chip_size;
  16. size_t file_size;
  17. size_t blocks_written;
  18. size_t block_size;
  19. float progress;
  20. SPIMemProgressViewType view_type;
  21. } SPIMemProgressViewModel;
  22. View* spi_mem_view_progress_get_view(SPIMemProgressView* app) {
  23. return app->view;
  24. }
  25. static void spi_mem_view_progress_draw_progress(Canvas* canvas, float progress) {
  26. FuriString* progress_str = furi_string_alloc();
  27. if(progress > 1.0) progress = 1.0;
  28. furi_string_printf(progress_str, "%d %%", (int)(progress * 100));
  29. elements_progress_bar(canvas, 13, 35, 100, progress);
  30. canvas_draw_str_aligned(
  31. canvas, 64, 25, AlignCenter, AlignTop, furi_string_get_cstr(progress_str));
  32. furi_string_free(progress_str);
  33. }
  34. static void
  35. spi_mem_view_progress_read_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) {
  36. canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Reading dump");
  37. spi_mem_view_progress_draw_progress(canvas, model->progress);
  38. elements_button_left(canvas, "Cancel");
  39. }
  40. static void
  41. spi_mem_view_progress_draw_size_warning(Canvas* canvas, SPIMemProgressViewModel* model) {
  42. if(model->file_size > model->chip_size) {
  43. canvas_draw_str_aligned(canvas, 64, 13, AlignCenter, AlignTop, "Size clamped to chip!");
  44. }
  45. if(model->chip_size > model->file_size) {
  46. canvas_draw_str_aligned(canvas, 64, 13, AlignCenter, AlignTop, "Size clamped to file!");
  47. }
  48. }
  49. static void
  50. spi_mem_view_progress_verify_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) {
  51. canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Verifying dump");
  52. spi_mem_view_progress_draw_size_warning(canvas, model);
  53. spi_mem_view_progress_draw_progress(canvas, model->progress);
  54. elements_button_center(canvas, "Skip");
  55. }
  56. static void
  57. spi_mem_view_progress_write_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) {
  58. canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Writing dump");
  59. spi_mem_view_progress_draw_size_warning(canvas, model);
  60. spi_mem_view_progress_draw_progress(canvas, model->progress);
  61. elements_button_left(canvas, "Cancel");
  62. }
  63. static void spi_mem_view_progress_draw_callback(Canvas* canvas, void* context) {
  64. SPIMemProgressViewModel* model = context;
  65. SPIMemProgressViewType view_type = model->view_type;
  66. if(view_type == SPIMemProgressViewTypeRead) {
  67. spi_mem_view_progress_read_draw_callback(canvas, model);
  68. } else if(view_type == SPIMemProgressViewTypeVerify) {
  69. spi_mem_view_progress_verify_draw_callback(canvas, model);
  70. } else if(view_type == SPIMemProgressViewTypeWrite) {
  71. spi_mem_view_progress_write_draw_callback(canvas, model);
  72. }
  73. }
  74. static bool
  75. spi_mem_view_progress_read_write_input_callback(InputEvent* event, SPIMemProgressView* app) {
  76. bool success = false;
  77. if(event->type == InputTypeShort && event->key == InputKeyLeft) {
  78. if(app->callback) {
  79. app->callback(app->cb_ctx);
  80. }
  81. success = true;
  82. }
  83. return success;
  84. }
  85. static bool
  86. spi_mem_view_progress_verify_input_callback(InputEvent* event, SPIMemProgressView* app) {
  87. bool success = false;
  88. if(event->type == InputTypeShort && event->key == InputKeyOk) {
  89. if(app->callback) {
  90. app->callback(app->cb_ctx);
  91. }
  92. success = true;
  93. }
  94. return success;
  95. }
  96. static bool spi_mem_view_progress_input_callback(InputEvent* event, void* context) {
  97. SPIMemProgressView* app = context;
  98. bool success = false;
  99. SPIMemProgressViewType view_type;
  100. with_view_model(
  101. app->view, SPIMemProgressViewModel * model, { view_type = model->view_type; }, true);
  102. if(view_type == SPIMemProgressViewTypeRead) {
  103. success = spi_mem_view_progress_read_write_input_callback(event, app);
  104. } else if(view_type == SPIMemProgressViewTypeVerify) {
  105. success = spi_mem_view_progress_verify_input_callback(event, app);
  106. } else if(view_type == SPIMemProgressViewTypeWrite) {
  107. success = spi_mem_view_progress_read_write_input_callback(event, app);
  108. }
  109. return success;
  110. }
  111. SPIMemProgressView* spi_mem_view_progress_alloc() {
  112. SPIMemProgressView* app = malloc(sizeof(SPIMemProgressView));
  113. app->view = view_alloc();
  114. view_allocate_model(app->view, ViewModelTypeLocking, sizeof(SPIMemProgressViewModel));
  115. view_set_context(app->view, app);
  116. view_set_draw_callback(app->view, spi_mem_view_progress_draw_callback);
  117. view_set_input_callback(app->view, spi_mem_view_progress_input_callback);
  118. spi_mem_view_progress_reset(app);
  119. return app;
  120. }
  121. void spi_mem_view_progress_free(SPIMemProgressView* app) {
  122. view_free(app->view);
  123. free(app);
  124. }
  125. void spi_mem_view_progress_set_read_callback(
  126. SPIMemProgressView* app,
  127. SPIMemProgressViewCallback callback,
  128. void* cb_ctx) {
  129. app->callback = callback;
  130. app->cb_ctx = cb_ctx;
  131. with_view_model(
  132. app->view,
  133. SPIMemProgressViewModel * model,
  134. { model->view_type = SPIMemProgressViewTypeRead; },
  135. true);
  136. }
  137. void spi_mem_view_progress_set_verify_callback(
  138. SPIMemProgressView* app,
  139. SPIMemProgressViewCallback callback,
  140. void* cb_ctx) {
  141. app->callback = callback;
  142. app->cb_ctx = cb_ctx;
  143. with_view_model(
  144. app->view,
  145. SPIMemProgressViewModel * model,
  146. { model->view_type = SPIMemProgressViewTypeVerify; },
  147. true);
  148. }
  149. void spi_mem_view_progress_set_write_callback(
  150. SPIMemProgressView* app,
  151. SPIMemProgressViewCallback callback,
  152. void* cb_ctx) {
  153. app->callback = callback;
  154. app->cb_ctx = cb_ctx;
  155. with_view_model(
  156. app->view,
  157. SPIMemProgressViewModel * model,
  158. { model->view_type = SPIMemProgressViewTypeWrite; },
  159. true);
  160. }
  161. void spi_mem_view_progress_set_chip_size(SPIMemProgressView* app, size_t chip_size) {
  162. with_view_model(
  163. app->view, SPIMemProgressViewModel * model, { model->chip_size = chip_size; }, true);
  164. }
  165. void spi_mem_view_progress_set_file_size(SPIMemProgressView* app, size_t file_size) {
  166. with_view_model(
  167. app->view, SPIMemProgressViewModel * model, { model->file_size = file_size; }, true);
  168. }
  169. void spi_mem_view_progress_set_block_size(SPIMemProgressView* app, size_t block_size) {
  170. with_view_model(
  171. app->view, SPIMemProgressViewModel * model, { model->block_size = block_size; }, true);
  172. }
  173. static size_t spi_mem_view_progress_set_total_size(SPIMemProgressViewModel* model) {
  174. size_t total_size = model->chip_size;
  175. if((model->chip_size > model->file_size) && model->view_type != SPIMemProgressViewTypeRead) {
  176. total_size = model->file_size;
  177. }
  178. return total_size;
  179. }
  180. void spi_mem_view_progress_inc_progress(SPIMemProgressView* app) {
  181. with_view_model(
  182. app->view,
  183. SPIMemProgressViewModel * model,
  184. {
  185. size_t total_size = spi_mem_view_progress_set_total_size(model);
  186. if(total_size == 0) total_size = 1;
  187. model->blocks_written++;
  188. model->progress =
  189. ((float)model->block_size * (float)model->blocks_written) / ((float)total_size);
  190. },
  191. true);
  192. }
  193. void spi_mem_view_progress_reset(SPIMemProgressView* app) {
  194. with_view_model(
  195. app->view,
  196. SPIMemProgressViewModel * model,
  197. {
  198. model->blocks_written = 0;
  199. model->block_size = 0;
  200. model->chip_size = 0;
  201. model->file_size = 0;
  202. model->progress = 0;
  203. model->view_type = SPIMemProgressViewTypeUnknown;
  204. },
  205. true);
  206. }