Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
		
						commit
						e64de44b73
					
				| @ -149,6 +149,7 @@ const AboutDialogScreen about_screens[] = { | |||||||
| const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); | const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); | ||||||
| 
 | 
 | ||||||
| int32_t about_settings_app(void* p) { | int32_t about_settings_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     DialogsApp* dialogs = furi_record_open("dialogs"); |     DialogsApp* dialogs = furi_record_open("dialogs"); | ||||||
|     DialogMessage* message = dialog_message_alloc(); |     DialogMessage* message = dialog_message_alloc(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| // app enter function
 | // app enter function
 | ||||||
| extern "C" int32_t accessor_app(void* p) { | extern "C" int32_t accessor_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     AccessorApp* app = new AccessorApp(); |     AccessorApp* app = new AccessorApp(); | ||||||
|     app->run(); |     app->run(); | ||||||
|     delete app; |     delete app; | ||||||
|  | |||||||
| @ -64,7 +64,7 @@ void AccessorAppViewManager::send_event(AccessorEvent* event) { | |||||||
|     furi_check(result == osOK); |     furi_check(result == osOK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t AccessorAppViewManager::previous_view_callback(void* context) { | uint32_t AccessorAppViewManager::previous_view_callback(void*) { | ||||||
|     if(event_queue != NULL) { |     if(event_queue != NULL) { | ||||||
|         AccessorEvent event; |         AccessorEvent event; | ||||||
|         event.type = AccessorEvent::Type::Back; |         event.type = AccessorEvent::Type::Back; | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ extern void crypto_on_system_start(); | |||||||
| extern void ibutton_on_system_start(); | extern void ibutton_on_system_start(); | ||||||
| extern void infrared_on_system_start(); | extern void infrared_on_system_start(); | ||||||
| extern void lfrfid_on_system_start(); | extern void lfrfid_on_system_start(); | ||||||
|  | extern void music_player_on_system_start(); | ||||||
| extern void nfc_on_system_start(); | extern void nfc_on_system_start(); | ||||||
| extern void storage_on_system_start(); | extern void storage_on_system_start(); | ||||||
| extern void subghz_on_system_start(); | extern void subghz_on_system_start(); | ||||||
| @ -280,6 +281,10 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { | |||||||
|     infrared_on_system_start, |     infrared_on_system_start, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef APP_MUSIC_PLAYER | ||||||
|  |     music_player_on_system_start, | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef APP_NFC | #ifdef APP_NFC | ||||||
|     nfc_on_system_start, |     nfc_on_system_start, | ||||||
| #endif | #endif | ||||||
| @ -332,7 +337,7 @@ const FlipperApplication FLIPPER_PLUGINS[] = { | |||||||
| #ifdef APP_MUSIC_PLAYER | #ifdef APP_MUSIC_PLAYER | ||||||
|     {.app = music_player_app, |     {.app = music_player_app, | ||||||
|      .name = "Music Player", |      .name = "Music Player", | ||||||
|      .stack_size = 1024, |      .stack_size = 2048, | ||||||
|      .icon = &A_Plugins_14, |      .icon = &A_Plugins_14, | ||||||
|      .flags = FlipperApplicationFlagDefault}, |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -66,6 +66,7 @@ void archive_free(ArchiveApp* archive) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t archive_app(void* p) { | int32_t archive_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     ArchiveApp* archive = archive_alloc(); |     ArchiveApp* archive = archive_alloc(); | ||||||
|     scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); |     scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); | ||||||
|     view_dispatcher_run(archive->view_dispatcher); |     view_dispatcher_run(archive->view_dispatcher); | ||||||
|  | |||||||
| @ -7,8 +7,8 @@ static const char* known_apps[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ArchiveAppTypeEnum archive_get_app_type(const char* path) { | ArchiveAppTypeEnum archive_get_app_type(const char* path) { | ||||||
|     for(size_t i = 0; i < SIZEOF_ARRAY(known_apps); i++) { |     for(size_t i = 0; i < COUNT_OF(known_apps); i++) { | ||||||
|         if(strncmp(path, known_apps[i], strlen(known_apps[i])) != STRING_FAILURE) { |         if(strncmp(path, known_apps[i], strlen(known_apps[i])) == 0) { | ||||||
|             return i; |             return i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -16,6 +16,7 @@ ArchiveAppTypeEnum archive_get_app_type(const char* path) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool archive_app_is_available(void* context, const char* path) { | bool archive_app_is_available(void* context, const char* path) { | ||||||
|  |     UNUSED(context); | ||||||
|     furi_assert(path); |     furi_assert(path); | ||||||
| 
 | 
 | ||||||
|     ArchiveAppTypeEnum app = archive_get_app_type(path); |     ArchiveAppTypeEnum app = archive_get_app_type(path); | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ static const ArchiveFileTypeEnum app_file_types[] = { | |||||||
|     [ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown, |     [ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static inline const ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { | static inline ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { | ||||||
|     return app_file_types[app]; |     return app_file_types[app]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,7 +6,8 @@ | |||||||
| bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { | bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { | ||||||
|     size_t array_size = files_array_size(model->files); |     size_t array_size = files_array_size(model->files); | ||||||
| 
 | 
 | ||||||
|     if((idx >= model->array_offset + array_size) || (idx < model->array_offset)) { |     if((idx >= (uint32_t)model->array_offset + array_size) || | ||||||
|  |        (idx < (uint32_t)model->array_offset)) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -20,12 +21,14 @@ void archive_update_offset(ArchiveBrowserView* browser) { | |||||||
|         browser->view, (ArchiveBrowserViewModel * model) { |         browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|             uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt; |             uint16_t bounds = model->item_cnt > 3 ? 2 : model->item_cnt; | ||||||
| 
 | 
 | ||||||
|             if(model->item_cnt > 3 && model->item_idx >= model->item_cnt - 1) { |             if((model->item_cnt > 3u) && (model->item_idx >= ((int32_t)model->item_cnt - 1))) { | ||||||
|                 model->list_offset = model->item_idx - 3; |                 model->list_offset = model->item_idx - 3; | ||||||
|             } else if(model->list_offset < model->item_idx - bounds) { |             } else if(model->list_offset < model->item_idx - bounds) { | ||||||
|                 model->list_offset = CLAMP(model->item_idx - 2, model->item_cnt - bounds, 0); |                 model->list_offset = | ||||||
|  |                     CLAMP(model->item_idx - 2, (int32_t)model->item_cnt - bounds, 0); | ||||||
|             } else if(model->list_offset > model->item_idx - bounds) { |             } else if(model->list_offset > model->item_idx - bounds) { | ||||||
|                 model->list_offset = CLAMP(model->item_idx - 1, model->item_cnt - bounds, 0); |                 model->list_offset = | ||||||
|  |                     CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return true; |             return true; | ||||||
| @ -77,9 +80,10 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) { | |||||||
|     with_view_model( |     with_view_model( | ||||||
|         browser->view, (ArchiveBrowserViewModel * model) { |         browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|             model->item_cnt = count; |             model->item_cnt = count; | ||||||
|             model->item_idx = CLAMP(model->item_idx, model->item_cnt - 1, 0); |             model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); | ||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
|  |     archive_update_offset(browser); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void archive_file_array_rm_selected(ArchiveBrowserView* browser) { | void archive_file_array_rm_selected(ArchiveBrowserView* browser) { | ||||||
| @ -93,7 +97,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { | |||||||
|                 model->item_idx - model->array_offset, |                 model->item_idx - model->array_offset, | ||||||
|                 model->item_idx - model->array_offset + 1); |                 model->item_idx - model->array_offset + 1); | ||||||
|             model->item_cnt--; |             model->item_cnt--; | ||||||
|             model->item_idx = CLAMP(model->item_idx, model->item_cnt - 1, 0); |             model->item_idx = CLAMP(model->item_idx, (int32_t)model->item_cnt - 1, 0); | ||||||
|             items_cnt = model->item_cnt; |             items_cnt = model->item_cnt; | ||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| @ -112,14 +116,14 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) { | |||||||
|         browser->view, (ArchiveBrowserViewModel * model) { |         browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|             ArchiveFile_t temp; |             ArchiveFile_t temp; | ||||||
|             size_t array_size = files_array_size(model->files) - 1; |             size_t array_size = files_array_size(model->files) - 1; | ||||||
|             uint8_t swap_idx = CLAMP(model->item_idx + dir, array_size, 0); |             uint8_t swap_idx = CLAMP((size_t)(model->item_idx + dir), array_size, 0u); | ||||||
| 
 | 
 | ||||||
|             if(model->item_idx == 0 && dir < 0) { |             if(model->item_idx == 0 && dir < 0) { | ||||||
|                 ArchiveFile_t_init(&temp); |                 ArchiveFile_t_init(&temp); | ||||||
|                 files_array_pop_at(&temp, model->files, array_size); |                 files_array_pop_at(&temp, model->files, array_size); | ||||||
|                 files_array_push_at(model->files, model->item_idx, temp); |                 files_array_push_at(model->files, model->item_idx, temp); | ||||||
|                 ArchiveFile_t_clear(&temp); |                 ArchiveFile_t_clear(&temp); | ||||||
|             } else if(model->item_idx == array_size && dir > 0) { |             } else if(((uint32_t)model->item_idx == array_size) && (dir > 0)) { | ||||||
|                 ArchiveFile_t_init(&temp); |                 ArchiveFile_t_init(&temp); | ||||||
|                 files_array_pop_at(&temp, model->files, 0); |                 files_array_pop_at(&temp, model->files, 0); | ||||||
|                 files_array_push_at(model->files, array_size, temp); |                 files_array_push_at(model->files, array_size, temp); | ||||||
| @ -156,7 +160,7 @@ bool archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { | |||||||
|                 } else { |                 } else { | ||||||
|                     offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 1; |                     offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 1; | ||||||
|                 } |                 } | ||||||
|                 offset_new = CLAMP(offset_new, model->item_cnt - FILE_LIST_BUF_LEN, 0); |                 offset_new = CLAMP(offset_new, (int32_t)model->item_cnt - FILE_LIST_BUF_LEN, 0); | ||||||
|             } |             } | ||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| @ -195,7 +199,7 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { | |||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         browser->view, (ArchiveBrowserViewModel * model) { |         browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|             idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0); |             idx = CLAMP(idx - model->array_offset, files_array_size(model->files), 0u); | ||||||
|             selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL; |             selected = files_array_size(model->files) ? files_array_get(model->files, idx) : NULL; | ||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| @ -246,6 +250,7 @@ void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | |||||||
|         }); |         }); | ||||||
| } | } | ||||||
| void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | ||||||
|  |     UNUSED(tab); // FIXME?
 | ||||||
|     furi_assert(browser); |     furi_assert(browser); | ||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
| @ -396,8 +401,6 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     archive_dir_count_items(browser, string_get_cstr(name)); |  | ||||||
| 
 |  | ||||||
|     if(string_cmp(browser->path, name) != 0) { |     if(string_cmp(browser->path, name) != 0) { | ||||||
|         with_view_model( |         with_view_model( | ||||||
|             browser->view, (ArchiveBrowserViewModel * model) { |             browser->view, (ArchiveBrowserViewModel * model) { | ||||||
| @ -410,6 +413,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { | |||||||
|         string_set(browser->path, name); |         string_set(browser->path, name); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     archive_dir_count_items(browser, string_get_cstr(name)); | ||||||
|     archive_switch_dir(browser, string_get_cstr(browser->path)); |     archive_switch_dir(browser, string_get_cstr(browser->path)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ static const ArchiveFileTypeEnum known_type[] = { | |||||||
|     [ArchiveTabBrowser] = ArchiveFileTypeUnknown, |     [ArchiveTabBrowser] = ArchiveFileTypeUnknown, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static inline const ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { | static inline ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { | ||||||
|     return known_type[tab]; |     return known_type[tab]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ void archive_set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* | |||||||
|     } else { |     } else { | ||||||
|         furi_assert(file_info); |         furi_assert(file_info); | ||||||
| 
 | 
 | ||||||
|         for(size_t i = 0; i < SIZEOF_ARRAY(known_ext); i++) { |         for(size_t i = 0; i < COUNT_OF(known_ext); i++) { | ||||||
|             if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; |             if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; | ||||||
|             if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { |             if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { | ||||||
|                 if(i == ArchiveFileTypeBadUsb) { |                 if(i == ArchiveFileTypeBadUsb) { | ||||||
|  | |||||||
| @ -31,6 +31,7 @@ static void archive_loader_callback(const void* message, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { | static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { | ||||||
|  |     UNUSED(browser); | ||||||
|     Loader* loader = furi_record_open("loader"); |     Loader* loader = furi_record_open("loader"); | ||||||
| 
 | 
 | ||||||
|     LoaderStatus status; |     LoaderStatus status; | ||||||
| @ -95,6 +96,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|             if(known_app) { |             if(known_app) { | ||||||
|                 archive_run_in_app(browser, selected); |                 archive_run_in_app(browser, selected); | ||||||
|             } |             } | ||||||
|  |             archive_show_file_menu(browser, false); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             break; |             break; | ||||||
|         case ArchiveBrowserEventFileMenuPin: |         case ArchiveBrowserEventFileMenuPin: | ||||||
|  | |||||||
| @ -106,17 +106,17 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { | |||||||
|     size_t array_size = files_array_size(model->files); |     size_t array_size = files_array_size(model->files); | ||||||
|     bool scrollbar = model->item_cnt > 4; |     bool scrollbar = model->item_cnt > 4; | ||||||
| 
 | 
 | ||||||
|     for(size_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { |     for(uint32_t i = 0; i < MIN(model->item_cnt, MENU_ITEMS); ++i) { | ||||||
|         string_t str_buff; |         string_t str_buff; | ||||||
|         char cstr_buff[MAX_NAME_LEN]; |         char cstr_buff[MAX_NAME_LEN]; | ||||||
|         size_t idx = CLAMP(i + model->list_offset, model->item_cnt, 0); |         int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); | ||||||
|         uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0; |         uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0; | ||||||
| 
 | 
 | ||||||
|         ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; |         ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; | ||||||
| 
 | 
 | ||||||
|         if(archive_is_item_in_array(model, idx)) { |         if(archive_is_item_in_array(model, idx)) { | ||||||
|             ArchiveFile_t* file = |             ArchiveFile_t* file = files_array_get( | ||||||
|                 files_array_get(model->files, CLAMP(idx - model->array_offset, array_size - 1, 0)); |                 model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); | ||||||
|             strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); |             strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); | ||||||
|             archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); |             archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); | ||||||
|             string_init_set_str(str_buff, cstr_buff); |             string_init_set_str(str_buff, cstr_buff); | ||||||
| @ -161,21 +161,21 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m | |||||||
|     canvas_draw_box(canvas, 107, 0, 20, 13); |     canvas_draw_box(canvas, 107, 0, 20, 13); | ||||||
| 
 | 
 | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     canvas_draw_frame(canvas, 1, 0, 50, 12); |     canvas_draw_rframe(canvas, 0, 0, 51, 13, 1); // frame
 | ||||||
|     canvas_draw_line(canvas, 0, 1, 0, 11); |     canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right
 | ||||||
|     canvas_draw_line(canvas, 1, 12, 49, 12); |     canvas_draw_line(canvas, 1, 11, 49, 11); // shadow bottom
 | ||||||
|     canvas_draw_str_aligned(canvas, 26, 9, AlignCenter, AlignBottom, tab_name); |     canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); | ||||||
| 
 | 
 | ||||||
|     canvas_draw_frame(canvas, 108, 0, 20, 12); |     canvas_draw_rframe(canvas, 107, 0, 21, 13, 1); | ||||||
|     canvas_draw_line(canvas, 107, 1, 107, 11); |     canvas_draw_line(canvas, 126, 1, 126, 11); | ||||||
|     canvas_draw_line(canvas, 108, 12, 126, 12); |     canvas_draw_line(canvas, 108, 11, 126, 11); | ||||||
| 
 | 
 | ||||||
|     if(model->move_fav) { |     if(model->move_fav) { | ||||||
|         canvas_draw_icon(canvas, 111, 4, &I_ButtonUp_7x4); |         canvas_draw_icon(canvas, 110, 4, &I_ButtonUp_7x4); | ||||||
|         canvas_draw_icon(canvas, 118, 4, &I_ButtonDown_7x4); |         canvas_draw_icon(canvas, 117, 4, &I_ButtonDown_7x4); | ||||||
|     } else { |     } else { | ||||||
|         canvas_draw_icon(canvas, 112, 2, &I_ButtonLeft_4x7); |         canvas_draw_icon(canvas, 111, 2, &I_ButtonLeft_4x7); | ||||||
|         canvas_draw_icon(canvas, 120, 2, &I_ButtonRight_4x7); |         canvas_draw_icon(canvas, 119, 2, &I_ButtonRight_4x7); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     canvas_set_color(canvas, ColorWhite); |     canvas_set_color(canvas, ColorWhite); | ||||||
| @ -216,7 +216,7 @@ static bool is_file_list_load_required(ArchiveBrowserViewModel* model) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(((model->array_offset + array_size) < model->item_cnt) && |     if(((model->array_offset + array_size) < model->item_cnt) && | ||||||
|        (model->item_idx > (model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { |        (model->item_idx > (int32_t)(model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -347,7 +347,7 @@ ArchiveBrowserView* browser_alloc() { | |||||||
|     browser->view = view_alloc(); |     browser->view = view_alloc(); | ||||||
|     view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel)); |     view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel)); | ||||||
|     view_set_context(browser->view, browser); |     view_set_context(browser->view, browser); | ||||||
|     view_set_draw_callback(browser->view, (ViewDrawCallback)archive_view_render); |     view_set_draw_callback(browser->view, archive_view_render); | ||||||
|     view_set_input_callback(browser->view, archive_view_input); |     view_set_input_callback(browser->view, archive_view_input); | ||||||
| 
 | 
 | ||||||
|     string_init(browser->path); |     string_init(browser->path); | ||||||
|  | |||||||
| @ -13,8 +13,8 @@ | |||||||
| #define MAX_NAME_LEN 255 | #define MAX_NAME_LEN 255 | ||||||
| #define MAX_EXT_LEN 6 | #define MAX_EXT_LEN 6 | ||||||
| #define FRAME_HEIGHT 12 | #define FRAME_HEIGHT 12 | ||||||
| #define MENU_ITEMS 4 | #define MENU_ITEMS 4u | ||||||
| #define MOVE_OFFSET 5 | #define MOVE_OFFSET 5u | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     ArchiveTabFavorites, |     ArchiveTabFavorites, | ||||||
|  | |||||||
| @ -31,10 +31,13 @@ void bad_usb_scene_file_select_on_enter(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool bad_usb_scene_file_select_on_event(void* context, SceneManagerEvent event) { | bool bad_usb_scene_file_select_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(event); | ||||||
|     // BadUsbApp* bad_usb = context;
 |     // BadUsbApp* bad_usb = context;
 | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void bad_usb_scene_file_select_on_exit(void* context) { | void bad_usb_scene_file_select_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     // BadUsbApp* bad_usb = context;
 |     // BadUsbApp* bad_usb = context;
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -142,6 +142,7 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c | |||||||
|     furi_assert(callback); |     furi_assert(callback); | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         bad_usb->view, (BadUsbModel * model) { |         bad_usb->view, (BadUsbModel * model) { | ||||||
|  |             UNUSED(model); | ||||||
|             bad_usb->callback = callback; |             bad_usb->callback = callback; | ||||||
|             bad_usb->context = context; |             bad_usb->context = context; | ||||||
|             return true; |             return true; | ||||||
|  | |||||||
| @ -13,6 +13,9 @@ static const char* bt_cli_address_types[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { | static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|     string_t buffer; |     string_t buffer; | ||||||
|     string_init(buffer); |     string_init(buffer); | ||||||
|     furi_hal_bt_dump_state(buffer); |     furi_hal_bt_dump_state(buffer); | ||||||
| @ -21,6 +24,7 @@ static void bt_cli_command_hci_info(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { | static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     int channel = 0; |     int channel = 0; | ||||||
|     int power = 0; |     int power = 0; | ||||||
| 
 | 
 | ||||||
| @ -47,6 +51,7 @@ static void bt_cli_command_carrier_tx(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { | static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     int channel = 0; |     int channel = 0; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
| @ -63,7 +68,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { | |||||||
| 
 | 
 | ||||||
|         while(!cli_cmd_interrupt_received(cli)) { |         while(!cli_cmd_interrupt_received(cli)) { | ||||||
|             osDelay(250); |             osDelay(250); | ||||||
|             printf("RSSI: %6.1f dB\r", furi_hal_bt_get_rssi()); |             printf("RSSI: %6.1f dB\r", (double)furi_hal_bt_get_rssi()); | ||||||
|             fflush(stdout); |             fflush(stdout); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -72,6 +77,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { | static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     int channel = 0; |     int channel = 0; | ||||||
|     int pattern = 0; |     int pattern = 0; | ||||||
|     int datarate = 1; |     int datarate = 1; | ||||||
| @ -115,6 +121,7 @@ static void bt_cli_command_packet_tx(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { | static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     int channel = 0; |     int channel = 0; | ||||||
|     int datarate = 1; |     int datarate = 1; | ||||||
| 
 | 
 | ||||||
| @ -133,11 +140,9 @@ static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { | |||||||
|         printf("Press CTRL+C to stop\r\n"); |         printf("Press CTRL+C to stop\r\n"); | ||||||
|         furi_hal_bt_start_packet_rx(channel, datarate); |         furi_hal_bt_start_packet_rx(channel, datarate); | ||||||
| 
 | 
 | ||||||
|         float rssi_raw = 0; |  | ||||||
|         while(!cli_cmd_interrupt_received(cli)) { |         while(!cli_cmd_interrupt_received(cli)) { | ||||||
|             osDelay(250); |             osDelay(250); | ||||||
|             rssi_raw = furi_hal_bt_get_rssi(); |             printf("RSSI: %03.1f dB\r", (double)furi_hal_bt_get_rssi()); | ||||||
|             printf("RSSI: %03.1f dB\r", rssi_raw); |  | ||||||
|             fflush(stdout); |             fflush(stdout); | ||||||
|         } |         } | ||||||
|         uint16_t packets_received = furi_hal_bt_stop_packet_test(); |         uint16_t packets_received = furi_hal_bt_stop_packet_test(); | ||||||
| @ -152,6 +157,8 @@ static void bt_cli_scan_callback(GapAddress address, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli_command_scan(Cli* cli, string_t args, void* context) { | static void bt_cli_command_scan(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(args); | ||||||
|     osMessageQueueId_t queue = osMessageQueueNew(20, sizeof(GapAddress), NULL); |     osMessageQueueId_t queue = osMessageQueueNew(20, sizeof(GapAddress), NULL); | ||||||
|     furi_hal_bt_start_scan(bt_cli_scan_callback, queue); |     furi_hal_bt_start_scan(bt_cli_scan_callback, queue); | ||||||
| 
 | 
 | ||||||
| @ -189,6 +196,7 @@ static void bt_cli_print_usage() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bt_cli(Cli* cli, string_t args, void* context) { | static void bt_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     furi_record_open("bt"); |     furi_record_open("bt"); | ||||||
| 
 | 
 | ||||||
|     string_t cmd; |     string_t cmd; | ||||||
|  | |||||||
| @ -19,10 +19,12 @@ void bt_debug_submenu_callback(void* context, uint32_t index) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t bt_debug_exit(void* context) { | uint32_t bt_debug_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return VIEW_NONE; |     return VIEW_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t bt_debug_start_view(void* context) { | uint32_t bt_debug_start_view(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return BtDebugAppViewSubmenu; |     return BtDebugAppViewSubmenu; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -94,6 +96,7 @@ void bt_debug_app_free(BtDebugApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t bt_debug_app(void* p) { | int32_t bt_debug_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     if(furi_hal_bt_get_radio_stack() != FuriHalBtStackHciLayer) { |     if(furi_hal_bt_get_radio_stack() != FuriHalBtStackHciLayer) { | ||||||
|         FURI_LOG_E(TAG, "Incorrect radio stack, replace with HciLayer for tests."); |         FURI_LOG_E(TAG, "Incorrect radio stack, replace with HciLayer for tests."); | ||||||
|         DialogsApp* dialogs = furi_record_open("dialogs"); |         DialogsApp* dialogs = furi_record_open("dialogs"); | ||||||
|  | |||||||
| @ -141,7 +141,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_carrier_test->bt_test, |         bt_carrier_test->bt_test, | ||||||
|         "Mode", |         "Mode", | ||||||
|         SIZEOF_ARRAY(bt_param_mode), |         COUNT_OF(bt_param_mode), | ||||||
|         bt_carrier_test_mode_changed, |         bt_carrier_test_mode_changed, | ||||||
|         bt_carrier_test); |         bt_carrier_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
| @ -151,7 +151,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_carrier_test->bt_test, |         bt_carrier_test->bt_test, | ||||||
|         "Channel", |         "Channel", | ||||||
|         SIZEOF_ARRAY(bt_param_channel), |         COUNT_OF(bt_param_channel), | ||||||
|         bt_carrier_test_channel_changed, |         bt_carrier_test_channel_changed, | ||||||
|         bt_carrier_test); |         bt_carrier_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
| @ -162,7 +162,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_carrier_test->bt_test, |         bt_carrier_test->bt_test, | ||||||
|         "Power", |         "Power", | ||||||
|         SIZEOF_ARRAY(bt_param_power), |         COUNT_OF(bt_param_power), | ||||||
|         bt_carrier_test_param_channel, |         bt_carrier_test_param_channel, | ||||||
|         bt_carrier_test); |         bt_carrier_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
|  | |||||||
| @ -109,7 +109,7 @@ BtPacketTest* bt_packet_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_packet_test->bt_test, |         bt_packet_test->bt_test, | ||||||
|         "Mode", |         "Mode", | ||||||
|         SIZEOF_ARRAY(bt_param_mode), |         COUNT_OF(bt_param_mode), | ||||||
|         bt_packet_test_mode_changed, |         bt_packet_test_mode_changed, | ||||||
|         bt_packet_test); |         bt_packet_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
| @ -119,7 +119,7 @@ BtPacketTest* bt_packet_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_packet_test->bt_test, |         bt_packet_test->bt_test, | ||||||
|         "Channel", |         "Channel", | ||||||
|         SIZEOF_ARRAY(bt_param_channel), |         COUNT_OF(bt_param_channel), | ||||||
|         bt_packet_test_channel_changed, |         bt_packet_test_channel_changed, | ||||||
|         bt_packet_test); |         bt_packet_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
| @ -129,7 +129,7 @@ BtPacketTest* bt_packet_test_alloc() { | |||||||
|     param = bt_test_param_add( |     param = bt_test_param_add( | ||||||
|         bt_packet_test->bt_test, |         bt_packet_test->bt_test, | ||||||
|         "Data rate", |         "Data rate", | ||||||
|         SIZEOF_ARRAY(bt_param_data_rate), |         COUNT_OF(bt_param_data_rate), | ||||||
|         bt_packet_test_param_channel, |         bt_packet_test_param_channel, | ||||||
|         bt_packet_test); |         bt_packet_test); | ||||||
|     bt_test_set_current_value_index(param, 0); |     bt_test_set_current_value_index(param, 0); | ||||||
|  | |||||||
| @ -99,7 +99,7 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     canvas_draw_str(canvas, 6, 60, model->message); |     canvas_draw_str(canvas, 6, 60, model->message); | ||||||
|     if(model->state == BtTestStateStarted) { |     if(model->state == BtTestStateStarted) { | ||||||
|         if(model->rssi != 0.0f) { |         if(model->rssi != 0.0f) { | ||||||
|             snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", model->rssi); |             snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi); | ||||||
|             canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); |             canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); | ||||||
|         } |         } | ||||||
|     } else if(model->state == BtTestStateStopped) { |     } else if(model->state == BtTestStateStopped) { | ||||||
|  | |||||||
| @ -33,10 +33,12 @@ void bt_hid_dialog_callback(DialogExResult result, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t bt_hid_exit_confirm_view(void* context) { | uint32_t bt_hid_exit_confirm_view(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return BtHidViewExitConfirm; |     return BtHidViewExitConfirm; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t bt_hid_exit(void* context) { | uint32_t bt_hid_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return VIEW_NONE; |     return VIEW_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -139,6 +141,7 @@ void bt_hid_app_free(BtHid* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t bt_hid_app(void* p) { | int32_t bt_hid_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     // Switch profile to Hid
 |     // Switch profile to Hid
 | ||||||
|     BtHid* app = bt_hid_app_alloc(); |     BtHid* app = bt_hid_app_alloc(); | ||||||
|     bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); |     bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); | ||||||
|  | |||||||
| @ -76,6 +76,7 @@ void bt_settings_app_free(BtSettingsApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| extern int32_t bt_settings_app(void* p) { | extern int32_t bt_settings_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     BtSettingsApp* app = bt_settings_app_alloc(); |     BtSettingsApp* app = bt_settings_app_alloc(); | ||||||
|     view_dispatcher_run(app->view_dispatcher); |     view_dispatcher_run(app->view_dispatcher); | ||||||
|     bt_settings_save(&app->settings); |     bt_settings_save(&app->settings); | ||||||
|  | |||||||
| @ -130,10 +130,12 @@ void cli_motd() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_nl(Cli* cli) { | void cli_nl(Cli* cli) { | ||||||
|  |     UNUSED(cli); | ||||||
|     printf("\r\n"); |     printf("\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_prompt(Cli* cli) { | void cli_prompt(Cli* cli) { | ||||||
|  |     UNUSED(cli); | ||||||
|     printf("\r\n>: %s", string_get_cstr(cli->line)); |     printf("\r\n>: %s", string_get_cstr(cli->line)); | ||||||
|     fflush(stdout); |     fflush(stdout); | ||||||
| } | } | ||||||
| @ -451,6 +453,7 @@ void cli_session_close(Cli* cli) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t cli_srv(void* p) { | int32_t cli_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     Cli* cli = cli_alloc(); |     Cli* cli = cli_alloc(); | ||||||
| 
 | 
 | ||||||
|     // Init basic cli commands
 |     // Init basic cli commands
 | ||||||
|  | |||||||
| @ -12,6 +12,8 @@ | |||||||
| #define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d" | #define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d" | ||||||
| 
 | 
 | ||||||
| void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) { | void cli_command_device_info_callback(const char* key, const char* value, bool last, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(last); | ||||||
|     printf("%-24s: %s\r\n", key, value); |     printf("%-24s: %s\r\n", key, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -20,11 +22,14 @@ void cli_command_device_info_callback(const char* key, const char* value, bool l | |||||||
|  * This command is intended to be used by humans |  * This command is intended to be used by humans | ||||||
|  */ |  */ | ||||||
| void cli_command_device_info(Cli* cli, string_t args, void* context) { | void cli_command_device_info(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|     furi_hal_info_get(cli_command_device_info_callback, context); |     furi_hal_info_get(cli_command_device_info_callback, context); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_help(Cli* cli, string_t args, void* context) { | void cli_command_help(Cli* cli, string_t args, void* context) { | ||||||
|     (void)args; |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|     printf("Commands we have:"); |     printf("Commands we have:"); | ||||||
| 
 | 
 | ||||||
|     // Command count
 |     // Command count
 | ||||||
| @ -62,6 +67,9 @@ void cli_command_help(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_date(Cli* cli, string_t args, void* context) { | void cli_command_date(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(context); | ||||||
|  | 
 | ||||||
|     FuriHalRtcDateTime datetime = {0}; |     FuriHalRtcDateTime datetime = {0}; | ||||||
| 
 | 
 | ||||||
|     if(string_size(args) > 0) { |     if(string_size(args) > 0) { | ||||||
| @ -135,6 +143,8 @@ void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* conte | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_log(Cli* cli, string_t args, void* context) { | void cli_command_log(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|     StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1); |     StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1); | ||||||
|     uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE]; |     uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE]; | ||||||
| 
 | 
 | ||||||
| @ -152,6 +162,8 @@ void cli_command_log(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_vibro(Cli* cli, string_t args, void* context) { | void cli_command_vibro(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(context); | ||||||
|     if(!string_cmp(args, "0")) { |     if(!string_cmp(args, "0")) { | ||||||
|         NotificationApp* notification = furi_record_open("notification"); |         NotificationApp* notification = furi_record_open("notification"); | ||||||
|         notification_message_block(notification, &sequence_reset_vibro); |         notification_message_block(notification, &sequence_reset_vibro); | ||||||
| @ -166,6 +178,8 @@ void cli_command_vibro(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_debug(Cli* cli, string_t args, void* context) { | void cli_command_debug(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(context); | ||||||
|     if(!string_cmp(args, "0")) { |     if(!string_cmp(args, "0")) { | ||||||
|         furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); |         furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); | ||||||
|         loader_update_menu(); |         loader_update_menu(); | ||||||
| @ -180,6 +194,8 @@ void cli_command_debug(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_led(Cli* cli, string_t args, void* context) { | void cli_command_led(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(context); | ||||||
|     // Get first word as light name
 |     // Get first word as light name
 | ||||||
|     NotificationMessage notification_led_message; |     NotificationMessage notification_led_message; | ||||||
|     string_t light_name; |     string_t light_name; | ||||||
| @ -233,6 +249,7 @@ void cli_command_led(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_gpio_set(Cli* cli, string_t args, void* context) { | void cli_command_gpio_set(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     char pin_names[][4] = { |     char pin_names[][4] = { | ||||||
|         "PC0", |         "PC0", | ||||||
|         "PC1", |         "PC1", | ||||||
| @ -313,6 +330,8 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | #else | ||||||
|  |         UNUSED(cli); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|         LL_GPIO_SetPinMode(gpio[num].port, gpio[num].pin, LL_GPIO_MODE_OUTPUT); |         LL_GPIO_SetPinMode(gpio[num].port, gpio[num].pin, LL_GPIO_MODE_OUTPUT); | ||||||
| @ -325,6 +344,10 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_ps(Cli* cli, string_t args, void* context) { | void cli_command_ps(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|  | 
 | ||||||
|     const uint8_t threads_num_max = 32; |     const uint8_t threads_num_max = 32; | ||||||
|     osThreadId_t threads_id[threads_num_max]; |     osThreadId_t threads_id[threads_num_max]; | ||||||
|     uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max); |     uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max); | ||||||
| @ -344,6 +367,10 @@ void cli_command_ps(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_free(Cli* cli, string_t args, void* context) { | void cli_command_free(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|  | 
 | ||||||
|     printf("Free heap size: %d\r\n", memmgr_get_free_heap()); |     printf("Free heap size: %d\r\n", memmgr_get_free_heap()); | ||||||
|     printf("Total heap size: %d\r\n", memmgr_get_total_heap()); |     printf("Total heap size: %d\r\n", memmgr_get_total_heap()); | ||||||
|     printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap()); |     printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap()); | ||||||
| @ -351,10 +378,18 @@ void cli_command_free(Cli* cli, string_t args, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_free_blocks(Cli* cli, string_t args, void* context) { | void cli_command_free_blocks(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|  | 
 | ||||||
|     memmgr_heap_printf_free_blocks(); |     memmgr_heap_printf_free_blocks(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cli_command_i2c(Cli* cli, string_t args, void* context) { | void cli_command_i2c(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  |     UNUSED(args); | ||||||
|  |     UNUSED(context); | ||||||
|  | 
 | ||||||
|     furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); |     furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); | ||||||
|     printf("Scanning external i2c on PC0(SCL)/PC1(SDA)\r\n" |     printf("Scanning external i2c on PC0(SCL)/PC1(SDA)\r\n" | ||||||
|            "Clock: 100khz, 7bit address\r\n" |            "Clock: 100khz, 7bit address\r\n" | ||||||
|  | |||||||
| @ -86,6 +86,7 @@ static void cli_vcp_deinit() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int32_t vcp_worker(void* context) { | static int32_t vcp_worker(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     bool tx_idle = true; |     bool tx_idle = true; | ||||||
|     size_t missed_rx = 0; |     size_t missed_rx = 0; | ||||||
|     uint8_t last_tx_pkt_len = 0; |     uint8_t last_tx_pkt_len = 0; | ||||||
| @ -148,7 +149,7 @@ static int32_t vcp_worker(void* context) { | |||||||
|                 if(len > 0) { |                 if(len > 0) { | ||||||
|                     furi_check( |                     furi_check( | ||||||
|                         xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == |                         xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == | ||||||
|                         len); |                         (size_t)len); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
| #ifdef CLI_VCP_DEBUG | #ifdef CLI_VCP_DEBUG | ||||||
| @ -275,16 +276,19 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { | static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { | ||||||
|  |     UNUSED(_cookie); | ||||||
|     cli_vcp_tx((const uint8_t*)data, size); |     cli_vcp_tx((const uint8_t*)data, size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_state_callback(void* context, uint8_t state) { | static void vcp_state_callback(void* context, uint8_t state) { | ||||||
|  |     UNUSED(context); | ||||||
|     if(state == 0) { |     if(state == 0) { | ||||||
|         osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); |         osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_on_cdc_control_line(void* context, uint8_t state) { | static void vcp_on_cdc_control_line(void* context, uint8_t state) { | ||||||
|  |     UNUSED(context); | ||||||
|     // bit 0: DTR state, bit 1: RTS state
 |     // bit 0: DTR state, bit 1: RTS state
 | ||||||
|     bool dtr = state & (1 << 0); |     bool dtr = state & (1 << 0); | ||||||
| 
 | 
 | ||||||
| @ -296,11 +300,13 @@ static void vcp_on_cdc_control_line(void* context, uint8_t state) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_on_cdc_rx(void* context) { | static void vcp_on_cdc_rx(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); |     uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); | ||||||
|     furi_check((ret & osFlagsError) == 0); |     furi_check((ret & osFlagsError) == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_on_cdc_tx_complete(void* context) { | static void vcp_on_cdc_tx_complete(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); |     osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -164,6 +164,7 @@ void crypto_cli_decrypt(Cli* cli, string_t args) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void crypto_cli_has_key(Cli* cli, string_t args) { | void crypto_cli_has_key(Cli* cli, string_t args) { | ||||||
|  |     UNUSED(cli); | ||||||
|     int key_slot = 0; |     int key_slot = 0; | ||||||
|     uint8_t iv[16]; |     uint8_t iv[16]; | ||||||
| 
 | 
 | ||||||
| @ -185,6 +186,7 @@ void crypto_cli_has_key(Cli* cli, string_t args) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void crypto_cli_store_key(Cli* cli, string_t args) { | void crypto_cli_store_key(Cli* cli, string_t args) { | ||||||
|  |     UNUSED(cli); | ||||||
|     int key_slot = 0; |     int key_slot = 0; | ||||||
|     int key_size = 0; |     int key_size = 0; | ||||||
|     string_t key_type; |     string_t key_type; | ||||||
| @ -277,6 +279,7 @@ void crypto_cli_store_key(Cli* cli, string_t args) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void crypto_cli(Cli* cli, string_t args, void* context) { | static void crypto_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     string_t cmd; |     string_t cmd; | ||||||
|     string_init(cmd); |     string_init(cmd); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ static void blink_test_update(void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void blink_test_draw_callback(Canvas* canvas, void* ctx) { | static void blink_test_draw_callback(Canvas* canvas, void* ctx) { | ||||||
|  |     UNUSED(ctx); | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_set_font(canvas, FontPrimary); |     canvas_set_font(canvas, FontPrimary); | ||||||
|     canvas_draw_str(canvas, 2, 10, "Blink application"); |     canvas_draw_str(canvas, 2, 10, "Blink application"); | ||||||
| @ -41,6 +42,7 @@ static void blink_test_input_callback(InputEvent* input_event, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t blink_test_app(void* p) { | int32_t blink_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(BlinkEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(BlinkEvent), NULL); | ||||||
| 
 | 
 | ||||||
|     // Configure view port
 |     // Configure view port
 | ||||||
|  | |||||||
| @ -70,10 +70,12 @@ static void display_test_submenu_callback(void* context, uint32_t index) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t display_test_previous_callback(void* context) { | static uint32_t display_test_previous_callback(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return DisplayTestViewSubmenu; |     return DisplayTestViewSubmenu; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t display_test_exit_callback(void* context) { | static uint32_t display_test_exit_callback(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return VIEW_NONE; |     return VIEW_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -210,6 +212,7 @@ void display_test_free(DisplayTest* instance) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t display_test_run(DisplayTest* instance) { | int32_t display_test_run(DisplayTest* instance) { | ||||||
|  |     UNUSED(instance); | ||||||
|     view_dispatcher_switch_to_view(instance->view_dispatcher, DisplayTestViewSubmenu); |     view_dispatcher_switch_to_view(instance->view_dispatcher, DisplayTestViewSubmenu); | ||||||
|     view_dispatcher_run(instance->view_dispatcher); |     view_dispatcher_run(instance->view_dispatcher); | ||||||
| 
 | 
 | ||||||
| @ -217,6 +220,8 @@ int32_t display_test_run(DisplayTest* instance) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t display_test_app(void* p) { | int32_t display_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|  | 
 | ||||||
|     DisplayTest* instance = display_test_alloc(); |     DisplayTest* instance = display_test_alloc(); | ||||||
| 
 | 
 | ||||||
|     int32_t ret = display_test_run(instance); |     int32_t ret = display_test_run(instance); | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ struct ViewDisplayTest { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void view_display_test_draw_callback_intro(Canvas* canvas, void* _model) { | static void view_display_test_draw_callback_intro(Canvas* canvas, void* _model) { | ||||||
|  |     UNUSED(_model); | ||||||
|     canvas_draw_str(canvas, 12, 24, "Use < and > to switch tests"); |     canvas_draw_str(canvas, 12, 24, "Use < and > to switch tests"); | ||||||
|     canvas_draw_str(canvas, 12, 36, "Use ^ and v to switch size"); |     canvas_draw_str(canvas, 12, 36, "Use ^ and v to switch size"); | ||||||
|     canvas_draw_str(canvas, 32, 48, "Use (o) to flip"); |     canvas_draw_str(canvas, 32, 48, "Use (o) to flip"); | ||||||
|  | |||||||
| @ -60,6 +60,7 @@ static void keypad_test_input_callback(InputEvent* input_event, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t keypad_test_app(void* p) { | int32_t keypad_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); | ||||||
|     furi_check(event_queue); |     furi_check(event_queue); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -70,6 +70,7 @@ static void text_box_test_input_callback(InputEvent* input_event, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t text_box_test_app(void* p) { | int32_t text_box_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); | ||||||
|     furi_check(event_queue); |     furi_check(event_queue); | ||||||
| 
 | 
 | ||||||
| @ -90,7 +91,7 @@ int32_t text_box_test_app(void* p) { | |||||||
|     Gui* gui = furi_record_open("gui"); |     Gui* gui = furi_record_open("gui"); | ||||||
|     gui_add_view_port(gui, view_port, GuiLayerFullscreen); |     gui_add_view_port(gui, view_port, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|     uint32_t test_renders_num = SIZEOF_ARRAY(text_box_test_render); |     uint32_t test_renders_num = COUNT_OF(text_box_test_render); | ||||||
|     InputEvent event; |     InputEvent event; | ||||||
|     while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { |     while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { | ||||||
|         TextBoxTestState* state = acquire_mutex_block(&state_mutex); |         TextBoxTestState* state = acquire_mutex_block(&state_mutex); | ||||||
|  | |||||||
| @ -80,11 +80,13 @@ static void uart_echo_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool uart_echo_view_input_callback(InputEvent* event, void* context) { | static bool uart_echo_view_input_callback(InputEvent* event, void* context) { | ||||||
|     bool consumed = false; |     UNUSED(event); | ||||||
|     return consumed; |     UNUSED(context); | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t uart_echo_exit(void* context) { | static uint32_t uart_echo_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return VIEW_NONE; |     return VIEW_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -170,7 +172,10 @@ static int32_t uart_echo_worker(void* context) { | |||||||
| 
 | 
 | ||||||
|             notification_message(app->notification, &sequence_notification); |             notification_message(app->notification, &sequence_notification); | ||||||
|             with_view_model( |             with_view_model( | ||||||
|                 app->view, (UartDumpModel * model) { return true; }); |                 app->view, (UartDumpModel * model) { | ||||||
|  |                     UNUSED(model); | ||||||
|  |                     return true; | ||||||
|  |                 }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -261,6 +266,7 @@ static void uart_echo_app_free(UartEchoApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t uart_echo_app(void* p) { | int32_t uart_echo_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     UartEchoApp* app = uart_echo_app_alloc(); |     UartEchoApp* app = uart_echo_app_alloc(); | ||||||
|     view_dispatcher_run(app->view_dispatcher); |     view_dispatcher_run(app->view_dispatcher); | ||||||
|     uart_echo_app_free(app); |     uart_echo_app_free(app); | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ typedef struct { | |||||||
| } UsbMouseEvent; | } UsbMouseEvent; | ||||||
| 
 | 
 | ||||||
| static void usb_mouse_render_callback(Canvas* canvas, void* ctx) { | static void usb_mouse_render_callback(Canvas* canvas, void* ctx) { | ||||||
|  |     UNUSED(ctx); | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
| 
 | 
 | ||||||
|     canvas_set_font(canvas, FontPrimary); |     canvas_set_font(canvas, FontPrimary); | ||||||
| @ -37,6 +38,7 @@ static void usb_mouse_input_callback(InputEvent* input_event, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t usb_mouse_app(void* p) { | int32_t usb_mouse_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(UsbMouseEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(UsbMouseEvent), NULL); | ||||||
|     furi_check(event_queue); |     furi_check(event_queue); | ||||||
|     ViewPort* view_port = view_port_alloc(); |     ViewPort* view_port = view_port_alloc(); | ||||||
|  | |||||||
| @ -51,6 +51,7 @@ void usb_test_submenu_callback(void* context, uint32_t index) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t usb_test_exit(void* context) { | uint32_t usb_test_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     return VIEW_NONE; |     return VIEW_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -113,6 +114,7 @@ void usb_test_app_free(UsbTestApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t usb_test_app(void* p) { | int32_t usb_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     UsbTestApp* app = usb_test_app_alloc(); |     UsbTestApp* app = usb_test_app_alloc(); | ||||||
| 
 | 
 | ||||||
|     view_dispatcher_run(app->view_dispatcher); |     view_dispatcher_run(app->view_dispatcher); | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <notification/notification_messages.h> | #include <notification/notification_messages.h> | ||||||
| 
 | 
 | ||||||
| void vibro_test_draw_callback(Canvas* canvas, void* ctx) { | void vibro_test_draw_callback(Canvas* canvas, void* ctx) { | ||||||
|  |     UNUSED(ctx); | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_set_font(canvas, FontPrimary); |     canvas_set_font(canvas, FontPrimary); | ||||||
|     canvas_draw_str(canvas, 2, 10, "Vibro application"); |     canvas_draw_str(canvas, 2, 10, "Vibro application"); | ||||||
| @ -22,6 +23,7 @@ void vibro_test_input_callback(InputEvent* input_event, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t vibro_test_app(void* p) { | int32_t vibro_test_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); | ||||||
| 
 | 
 | ||||||
|     // Configure view port
 |     // Configure view port
 | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include <gui/view_stack.h> | #include <gui/view_stack.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
|  | #include <furi_hal.h> | ||||||
| #include <m-string.h> | #include <m-string.h> | ||||||
| #include <portmacro.h> | #include <portmacro.h> | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| @ -364,6 +365,7 @@ static bool animation_manager_is_valid_idle_animation( | |||||||
| 
 | 
 | ||||||
| static StorageAnimation* | static StorageAnimation* | ||||||
|     animation_manager_select_idle_animation(AnimationManager* animation_manager) { |     animation_manager_select_idle_animation(AnimationManager* animation_manager) { | ||||||
|  |     UNUSED(animation_manager); | ||||||
|     StorageAnimationList_t animation_list; |     StorageAnimationList_t animation_list; | ||||||
|     StorageAnimationList_init(animation_list); |     StorageAnimationList_init(animation_list); | ||||||
|     animation_storage_fill_animation_list(&animation_list); |     animation_storage_fill_animation_list(&animation_list); | ||||||
| @ -390,7 +392,7 @@ static StorageAnimation* | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint32_t lucky_number = random() % whole_weight; |     uint32_t lucky_number = furi_hal_random_get() % whole_weight; | ||||||
|     uint32_t weight = 0; |     uint32_t weight = 0; | ||||||
| 
 | 
 | ||||||
|     StorageAnimation* selected = NULL; |     StorageAnimation* selected = NULL; | ||||||
|  | |||||||
| @ -130,7 +130,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis | |||||||
|     flipper_format_free(file); |     flipper_format_free(file); | ||||||
| 
 | 
 | ||||||
|     // add hard-coded animations
 |     // add hard-coded animations
 | ||||||
|     for(int i = 0; i < dolphin_internal_size; ++i) { |     for(size_t i = 0; i < dolphin_internal_size; ++i) { | ||||||
|         StorageAnimationList_push_back(*animation_list, (StorageAnimation*)&dolphin_internal[i]); |         StorageAnimationList_push_back(*animation_list, (StorageAnimation*)&dolphin_internal[i]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -142,7 +142,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { | |||||||
|     furi_assert(strlen(name)); |     furi_assert(strlen(name)); | ||||||
|     StorageAnimation* storage_animation = NULL; |     StorageAnimation* storage_animation = NULL; | ||||||
| 
 | 
 | ||||||
|     for(int i = 0; i < dolphin_blocking_size; ++i) { |     for(size_t i = 0; i < dolphin_blocking_size; ++i) { | ||||||
|         if(!strcmp(dolphin_blocking[i].manifest_info.name, name)) { |         if(!strcmp(dolphin_blocking[i].manifest_info.name, name)) { | ||||||
|             storage_animation = (StorageAnimation*)&dolphin_blocking[i]; |             storage_animation = (StorageAnimation*)&dolphin_blocking[i]; | ||||||
|             break; |             break; | ||||||
| @ -150,7 +150,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(!storage_animation) { |     if(!storage_animation) { | ||||||
|         for(int i = 0; i < dolphin_internal_size; ++i) { |         for(size_t i = 0; i < dolphin_internal_size; ++i) { | ||||||
|             if(!strcmp(dolphin_internal[i].manifest_info.name, name)) { |             if(!strcmp(dolphin_internal[i].manifest_info.name, name)) { | ||||||
|                 storage_animation = (StorageAnimation*)&dolphin_internal[i]; |                 storage_animation = (StorageAnimation*)&dolphin_internal[i]; | ||||||
|                 break; |                 break; | ||||||
| @ -365,7 +365,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo | |||||||
|         animation->frame_bubble_sequences = |         animation->frame_bubble_sequences = | ||||||
|             malloc(sizeof(FrameBubble*) * animation->frame_bubble_sequences_count); |             malloc(sizeof(FrameBubble*) * animation->frame_bubble_sequences_count); | ||||||
| 
 | 
 | ||||||
|         uint32_t current_slot = 0; |         int32_t current_slot = 0; | ||||||
|         for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { |         for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { | ||||||
|             FURI_CONST_ASSIGN_PTR( |             FURI_CONST_ASSIGN_PTR( | ||||||
|                 animation->frame_bubble_sequences[i], malloc(sizeof(FrameBubble))); |                 animation->frame_bubble_sequences[i], malloc(sizeof(FrameBubble))); | ||||||
| @ -374,7 +374,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo | |||||||
|         const FrameBubble* bubble = animation->frame_bubble_sequences[0]; |         const FrameBubble* bubble = animation->frame_bubble_sequences[0]; | ||||||
|         int8_t index = -1; |         int8_t index = -1; | ||||||
|         for(;;) { |         for(;;) { | ||||||
|             if(!flipper_format_read_uint32(ff, "Slot", ¤t_slot, 1)) break; |             if(!flipper_format_read_int32(ff, "Slot", ¤t_slot, 1)) break; | ||||||
|             if((current_slot != 0) && (index == -1)) break; |             if((current_slot != 0) && (index == -1)) break; | ||||||
| 
 | 
 | ||||||
|             if(current_slot == index) { |             if(current_slot == index) { | ||||||
|  | |||||||
| @ -100,7 +100,8 @@ static const FrameBubble* | |||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint8_t index = random() % (active ? model->active_bubbles : model->passive_bubbles); |     uint8_t index = | ||||||
|  |         furi_hal_random_get() % (active ? model->active_bubbles : model->passive_bubbles); | ||||||
|     const BubbleAnimation* animation = model->current; |     const BubbleAnimation* animation = model->current; | ||||||
| 
 | 
 | ||||||
|     for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { |     for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { | ||||||
|  | |||||||
| @ -33,6 +33,7 @@ static void desktop_loader_callback(const void* message, void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void desktop_lock_icon_callback(Canvas* canvas, void* context) { | static void desktop_lock_icon_callback(Canvas* canvas, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); |     canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); | ||||||
| } | } | ||||||
| @ -298,6 +299,7 @@ static bool desktop_is_first_start() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t desktop_srv(void* p) { | int32_t desktop_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     Desktop* desktop = desktop_alloc(); |     Desktop* desktop = desktop_alloc(); | ||||||
| 
 | 
 | ||||||
|     bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); |     bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); | ||||||
|  | |||||||
| @ -53,4 +53,5 @@ bool desktop_settings_scene_pin_disable_on_event(void* context, SceneManagerEven | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_settings_scene_pin_disable_on_exit(void* context) { | void desktop_settings_scene_pin_disable_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ static void pin_error_back_callback(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void pin_error_done_callback(const PinCode* pin_code, void* context) { | static void pin_error_done_callback(const PinCode* pin_code, void* context) { | ||||||
|  |     UNUSED(pin_code); | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     DesktopSettingsApp* app = context; |     DesktopSettingsApp* app = context; | ||||||
|     view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); |     view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); | ||||||
|  | |||||||
| @ -41,4 +41,5 @@ bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManager | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_settings_scene_pin_setup_howto_on_exit(void* context) { | void desktop_settings_scene_pin_setup_howto_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -47,5 +47,6 @@ bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_fault_on_exit(void* context) { | void desktop_scene_fault_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     furi_hal_rtc_set_fault_data(0); |     furi_hal_rtc_set_fault_data(0); | ||||||
| } | } | ||||||
|  | |||||||
| @ -50,4 +50,5 @@ bool desktop_scene_first_start_on_event(void* context, SceneManagerEvent event) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_first_start_on_exit(void* context) { | void desktop_scene_first_start_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -81,4 +81,5 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_lock_menu_on_exit(void* context) { | void desktop_scene_lock_menu_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -109,4 +109,5 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_locked_on_exit(void* context) { | void desktop_scene_locked_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -43,4 +43,5 @@ bool desktop_scene_pin_timeout_on_event(void* context, SceneManagerEvent event) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void desktop_scene_pin_timeout_on_exit(void* context) { | void desktop_scene_pin_timeout_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -51,6 +51,8 @@ static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool desktop_view_pin_timeout_input(InputEvent* event, void* context) { | static bool desktop_view_pin_timeout_input(InputEvent* event, void* context) { | ||||||
|  |     UNUSED(event); | ||||||
|  |     UNUSED(context); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ static DialogsApp* dialogs_app_alloc() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) { | static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) { | ||||||
|  |     UNUSED(app); | ||||||
|     switch(message->command) { |     switch(message->command) { | ||||||
|     case DialogsAppCommandFileOpen: |     case DialogsAppCommandFileOpen: | ||||||
|         message->return_data->bool_value = |         message->return_data->bool_value = | ||||||
| @ -25,6 +26,7 @@ static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* mess | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t dialogs_srv(void* p) { | int32_t dialogs_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     DialogsApp* app = dialogs_app_alloc(); |     DialogsApp* app = dialogs_app_alloc(); | ||||||
|     furi_record_create("dialogs", app); |     furi_record_create("dialogs", app); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -118,6 +118,7 @@ void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) { | void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) { | ||||||
|  |     UNUSED(dolphin); | ||||||
|     if(event->flag) { |     if(event->flag) { | ||||||
|         osEventFlagsSet(event->flag, DOLPHIN_LOCK_EVENT_FLAG); |         osEventFlagsSet(event->flag, DOLPHIN_LOCK_EVENT_FLAG); | ||||||
|     } |     } | ||||||
| @ -149,6 +150,7 @@ static void dolphin_update_clear_limits_timer_period(Dolphin* dolphin) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t dolphin_srv(void* p) { | int32_t dolphin_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     Dolphin* dolphin = dolphin_alloc(); |     Dolphin* dolphin = dolphin_alloc(); | ||||||
|     furi_record_create("dolphin", dolphin); |     furi_record_create("dolphin", dolphin); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
|     uint32_t flags; |     uint32_t flags; | ||||||
|     uint32_t icounter; |     uint32_t icounter; | ||||||
|     uint32_t butthurt; |     int32_t butthurt; | ||||||
|     uint64_t timestamp; |     uint64_t timestamp; | ||||||
| } DolphinStoreData; | } DolphinStoreData; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -90,6 +90,7 @@ static void render_callback(Canvas* canvas, void* ctx) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t passport_app(void* p) { | int32_t passport_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     osSemaphoreId_t semaphore = osSemaphoreNew(1, 0, NULL); |     osSemaphoreId_t semaphore = osSemaphoreNew(1, 0, NULL); | ||||||
|     furi_assert(semaphore); |     furi_assert(semaphore); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -95,6 +95,7 @@ void gpio_app_free(GpioApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t gpio_app(void* p) { | int32_t gpio_app(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     GpioApp* gpio_app = gpio_app_alloc(); |     GpioApp* gpio_app = gpio_app_alloc(); | ||||||
| 
 | 
 | ||||||
|     view_dispatcher_run(gpio_app->view_dispatcher); |     view_dispatcher_run(gpio_app->view_dispatcher); | ||||||
|  | |||||||
| @ -19,9 +19,12 @@ void gpio_scene_test_on_enter(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) { | bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(event); | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gpio_scene_test_on_exit(void* context) { | void gpio_scene_test_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     gpio_item_configure_all_pins(GpioModeAnalog); |     gpio_item_configure_all_pins(GpioModeAnalog); | ||||||
| } | } | ||||||
|  | |||||||
| @ -28,12 +28,9 @@ static const uint32_t baudrate_list[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) { | bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) { | ||||||
|     //GpioApp* app = context;
 |     UNUSED(context); | ||||||
|     bool consumed = false; |     UNUSED(event); | ||||||
| 
 |     return false; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |  | ||||||
|     } |  | ||||||
|     return consumed; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void line_vcp_cb(VariableItem* item) { | static void line_vcp_cb(VariableItem* item) { | ||||||
|  | |||||||
| @ -101,6 +101,7 @@ static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) { | static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) { | ||||||
|  |     UNUSED(usb_uart); | ||||||
|     furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); |     furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); | ||||||
|     FURI_LOG_I("", "Deinit %d", vcp_ch); |     FURI_LOG_I("", "Deinit %d", vcp_ch); | ||||||
|     if(vcp_ch != 0) { |     if(vcp_ch != 0) { | ||||||
| @ -120,6 +121,7 @@ static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) { | static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) { | ||||||
|  |     UNUSED(usb_uart); | ||||||
|     furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL); |     furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL); | ||||||
|     if(uart_ch == FuriHalUartIdUSART1) |     if(uart_ch == FuriHalUartIdUSART1) | ||||||
|         furi_hal_console_enable(); |         furi_hal_console_enable(); | ||||||
| @ -143,7 +145,7 @@ static void usb_uart_set_baudrate(UsbUartBridge* usb_uart, uint32_t baudrate) { | |||||||
| 
 | 
 | ||||||
| static void usb_uart_update_ctrl_lines(UsbUartBridge* usb_uart) { | static void usb_uart_update_ctrl_lines(UsbUartBridge* usb_uart) { | ||||||
|     if(usb_uart->cfg.flow_pins != 0) { |     if(usb_uart->cfg.flow_pins != 0) { | ||||||
|         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); |         furi_assert((size_t)(usb_uart->cfg.flow_pins - 1) < COUNT_OF(flow_pins)); | ||||||
|         uint8_t state = furi_hal_cdc_get_ctrl_line_state(usb_uart->cfg.vcp_ch); |         uint8_t state = furi_hal_cdc_get_ctrl_line_state(usb_uart->cfg.vcp_ch); | ||||||
| 
 | 
 | ||||||
|         furi_hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][0], !(state & USB_CDC_BIT_RTS)); |         furi_hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][0], !(state & USB_CDC_BIT_RTS)); | ||||||
| @ -171,7 +173,7 @@ static int32_t usb_uart_worker(void* context) { | |||||||
|     usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch); |     usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch); | ||||||
|     usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); |     usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); | ||||||
|     if(usb_uart->cfg.flow_pins != 0) { |     if(usb_uart->cfg.flow_pins != 0) { | ||||||
|         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); |         furi_assert((size_t)(usb_uart->cfg.flow_pins - 1) < COUNT_OF(flow_pins)); | ||||||
|         furi_hal_gpio_init_simple( |         furi_hal_gpio_init_simple( | ||||||
|             flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); |             flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); | ||||||
|         furi_hal_gpio_init_simple( |         furi_hal_gpio_init_simple( | ||||||
| @ -238,9 +240,7 @@ static int32_t usb_uart_worker(void* context) { | |||||||
|                         flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); |                         flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); | ||||||
|                 } |                 } | ||||||
|                 if(usb_uart->cfg_new.flow_pins != 0) { |                 if(usb_uart->cfg_new.flow_pins != 0) { | ||||||
|                     furi_assert( |                     furi_assert((size_t)(usb_uart->cfg_new.flow_pins - 1) < COUNT_OF(flow_pins)); | ||||||
|                         (usb_uart->cfg_new.flow_pins - 1) < |  | ||||||
|                         (sizeof(flow_pins) / sizeof(flow_pins[0]))); |  | ||||||
|                     furi_hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
|                         flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); |                         flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); | ||||||
|                     furi_hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
| @ -318,14 +318,18 @@ static void vcp_on_cdc_rx(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_state_callback(void* context, uint8_t state) { | static void vcp_state_callback(void* context, uint8_t state) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_on_cdc_control_line(void* context, uint8_t state) { | static void vcp_on_cdc_control_line(void* context, uint8_t state) { | ||||||
|  |     UNUSED(state); | ||||||
|     UsbUartBridge* usb_uart = (UsbUartBridge*)context; |     UsbUartBridge* usb_uart = (UsbUartBridge*)context; | ||||||
|     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet); |     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { | static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { | ||||||
|  |     UNUSED(config); | ||||||
|     UsbUartBridge* usb_uart = (UsbUartBridge*)context; |     UsbUartBridge* usb_uart = (UsbUartBridge*)context; | ||||||
|     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtLineCfgSet); |     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtLineCfgSet); | ||||||
| } | } | ||||||
|  | |||||||
| @ -123,6 +123,7 @@ void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback, | |||||||
|     furi_assert(callback); |     furi_assert(callback); | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         gpio_test->view, (GpioTestModel * model) { |         gpio_test->view, (GpioTestModel * model) { | ||||||
|  |             UNUSED(model); | ||||||
|             gpio_test->callback = callback; |             gpio_test->callback = callback; | ||||||
|             gpio_test->context = context; |             gpio_test->context = context; | ||||||
|             return false; |             return false; | ||||||
|  | |||||||
| @ -130,6 +130,7 @@ void gpio_usb_uart_set_callback(GpioUsbUart* usb_uart, GpioUsbUartCallback callb | |||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         usb_uart->view, (GpioUsbUartModel * model) { |         usb_uart->view, (GpioUsbUartModel * model) { | ||||||
|  |             UNUSED(model); | ||||||
|             usb_uart->callback = callback; |             usb_uart->callback = callback; | ||||||
|             usb_uart->context = context; |             usb_uart->context = context; | ||||||
|             return false; |             return false; | ||||||
|  | |||||||
| @ -47,10 +47,9 @@ bool gui_redraw_fs(Gui* gui) { | |||||||
| 
 | 
 | ||||||
| static void gui_redraw_status_bar(Gui* gui, bool need_attention) { | static void gui_redraw_status_bar(Gui* gui, bool need_attention) { | ||||||
|     ViewPortArray_it_t it; |     ViewPortArray_it_t it; | ||||||
|     uint8_t x; |     uint8_t left_used = 0; | ||||||
|     uint8_t x_used = 0; |     uint8_t right_used = 0; | ||||||
|     uint8_t width; |     uint8_t width; | ||||||
|     ViewPort* view_port; |  | ||||||
|     canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); |     canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); | ||||||
|     canvas_frame_set( |     canvas_frame_set( | ||||||
|         gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); |         gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); | ||||||
| @ -69,100 +68,126 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { | |||||||
|     canvas_set_bitmap_mode(gui->canvas, 0); |     canvas_set_bitmap_mode(gui->canvas, 0); | ||||||
| 
 | 
 | ||||||
|     // Right side
 |     // Right side
 | ||||||
|     x = GUI_DISPLAY_WIDTH; |     uint8_t x = GUI_DISPLAY_WIDTH - 1; | ||||||
|     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); |     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); | ||||||
|     while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { |     while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) { | ||||||
|         // Render view_port;
 |         ViewPort* view_port = *ViewPortArray_ref(it); | ||||||
|         view_port = *ViewPortArray_ref(it); |  | ||||||
|         if(view_port_is_enabled(view_port)) { |         if(view_port_is_enabled(view_port)) { | ||||||
|             width = view_port_get_width(view_port); |             width = view_port_get_width(view_port); | ||||||
|             if(!width) width = 8; |             if(!width) width = 8; | ||||||
|             x_used += width; |             // Recalculate next position
 | ||||||
|  |             right_used += (width + 2); | ||||||
|             x -= (width + 2); |             x -= (width + 2); | ||||||
|  |             // Prepare work area background
 | ||||||
|             canvas_frame_set( |             canvas_frame_set( | ||||||
|                 gui->canvas, x - 3, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); |  | ||||||
| 
 |  | ||||||
|             canvas_set_color(gui->canvas, ColorWhite); |  | ||||||
|             canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); |  | ||||||
|             canvas_set_color(gui->canvas, ColorBlack); |  | ||||||
| 
 |  | ||||||
|             canvas_draw_rframe( |  | ||||||
|                 gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); |  | ||||||
|             canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); |  | ||||||
|             canvas_draw_line( |  | ||||||
|                 gui->canvas, |                 gui->canvas, | ||||||
|                 2, |                 x - 1, | ||||||
|                 canvas_height(gui->canvas) - 2, |                 GUI_STATUS_BAR_Y + 1, | ||||||
|                 canvas_width(gui->canvas) - 2, |                 width + 2, | ||||||
|                 canvas_height(gui->canvas) - 2); |                 GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); | ||||||
| 
 |             canvas_set_color(gui->canvas, ColorWhite); | ||||||
|  |             canvas_draw_box( | ||||||
|  |                 gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); | ||||||
|  |             canvas_set_color(gui->canvas, ColorBlack); | ||||||
|  |             // ViewPort draw
 | ||||||
|             canvas_frame_set( |             canvas_frame_set( | ||||||
|                 gui->canvas, x, GUI_STATUS_BAR_Y + 1, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); |                 gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); | ||||||
| 
 |  | ||||||
|             view_port_draw(view_port, gui->canvas); |             view_port_draw(view_port, gui->canvas); | ||||||
|         } |         } | ||||||
|         ViewPortArray_next(it); |         ViewPortArray_next(it); | ||||||
|     } |     } | ||||||
|     // Left side
 |     // Draw frame around icons on the right
 | ||||||
|     x = 0; |     if(right_used) { | ||||||
|     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); |  | ||||||
|     while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { |  | ||||||
|         // Render view_port;
 |  | ||||||
|         view_port = *ViewPortArray_ref(it); |  | ||||||
|         if(view_port_is_enabled(view_port)) { |  | ||||||
|             width = view_port_get_width(view_port); |  | ||||||
|             if(!width) width = 8; |  | ||||||
|             x_used += width; |  | ||||||
| 
 |  | ||||||
|         canvas_frame_set( |         canvas_frame_set( | ||||||
|                 gui->canvas, 0, GUI_STATUS_BAR_Y, x + width + 5, GUI_STATUS_BAR_HEIGHT); |             gui->canvas, | ||||||
|  |             GUI_DISPLAY_WIDTH - 3 - right_used, | ||||||
|  |             GUI_STATUS_BAR_Y, | ||||||
|  |             right_used + 3, | ||||||
|  |             GUI_STATUS_BAR_HEIGHT); | ||||||
|  |         canvas_set_color(gui->canvas, ColorBlack); | ||||||
|         canvas_draw_rframe( |         canvas_draw_rframe( | ||||||
|             gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); |             gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); | ||||||
|             canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); |  | ||||||
|         canvas_draw_line( |         canvas_draw_line( | ||||||
|             gui->canvas, |             gui->canvas, | ||||||
|                 2, |             canvas_width(gui->canvas) - 2, | ||||||
|  |             1, | ||||||
|  |             canvas_width(gui->canvas) - 2, | ||||||
|  |             canvas_height(gui->canvas) - 2); | ||||||
|  |         canvas_draw_line( | ||||||
|  |             gui->canvas, | ||||||
|  |             1, | ||||||
|             canvas_height(gui->canvas) - 2, |             canvas_height(gui->canvas) - 2, | ||||||
|             canvas_width(gui->canvas) - 2, |             canvas_width(gui->canvas) - 2, | ||||||
|             canvas_height(gui->canvas) - 2); |             canvas_height(gui->canvas) - 2); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|             canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); |     // Left side
 | ||||||
| 
 |     x = 2; | ||||||
|             canvas_set_color(gui->canvas, ColorWhite); |     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); | ||||||
|             canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); |     while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { | ||||||
|             canvas_set_color(gui->canvas, ColorBlack); |         ViewPort* view_port = *ViewPortArray_ref(it); | ||||||
| 
 |         if(view_port_is_enabled(view_port)) { | ||||||
|  |             width = view_port_get_width(view_port); | ||||||
|  |             if(!width) width = 8; | ||||||
|  |             // Prepare work area background
 | ||||||
|             canvas_frame_set( |             canvas_frame_set( | ||||||
|                 gui->canvas, x + 3, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); |                 gui->canvas, | ||||||
|  |                 x - 1, | ||||||
|  |                 GUI_STATUS_BAR_Y + 1, | ||||||
|  |                 width + 2, | ||||||
|  |                 GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); | ||||||
|  |             canvas_set_color(gui->canvas, ColorWhite); | ||||||
|  |             canvas_draw_box( | ||||||
|  |                 gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); | ||||||
|  |             canvas_set_color(gui->canvas, ColorBlack); | ||||||
|  |             // ViewPort draw
 | ||||||
|  |             canvas_frame_set( | ||||||
|  |                 gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); | ||||||
|             view_port_draw(view_port, gui->canvas); |             view_port_draw(view_port, gui->canvas); | ||||||
| 
 |             // Recalculate next position
 | ||||||
|  |             left_used += (width + 2); | ||||||
|             x += (width + 2); |             x += (width + 2); | ||||||
|         } |         } | ||||||
|         ViewPortArray_next(it); |         ViewPortArray_next(it); | ||||||
|     } |     } | ||||||
| 
 |     // Extra notification
 | ||||||
|     if(need_attention) { |     if(need_attention) { | ||||||
|         width = icon_get_width(&I_Attention_5x8); |         width = icon_get_width(&I_Attention_5x8); | ||||||
|         canvas_frame_set(gui->canvas, 0, GUI_STATUS_BAR_Y, x + width + 5, GUI_STATUS_BAR_HEIGHT); |         // Prepare work area background
 | ||||||
|  |         canvas_frame_set( | ||||||
|  |             gui->canvas, | ||||||
|  |             x - 1, | ||||||
|  |             GUI_STATUS_BAR_Y + 1, | ||||||
|  |             width + 2, | ||||||
|  |             GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); | ||||||
|  |         canvas_set_color(gui->canvas, ColorWhite); | ||||||
|  |         canvas_draw_box(gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); | ||||||
|  |         canvas_set_color(gui->canvas, ColorBlack); | ||||||
|  |         // Draw Icon
 | ||||||
|  |         canvas_frame_set( | ||||||
|  |             gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); | ||||||
|  |         canvas_draw_icon(gui->canvas, 0, 0, &I_Attention_5x8); | ||||||
|  |         // Recalculate next position
 | ||||||
|  |         left_used += (width + 2); | ||||||
|  |         x += (width + 2); | ||||||
|  |     } | ||||||
|  |     // Draw frame around icons on the left
 | ||||||
|  |     if(left_used) { | ||||||
|  |         canvas_frame_set(gui->canvas, 0, 0, left_used + 3, GUI_STATUS_BAR_HEIGHT); | ||||||
|         canvas_draw_rframe( |         canvas_draw_rframe( | ||||||
|             gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); |             gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); | ||||||
|         canvas_draw_line(gui->canvas, 1, 1, 1, canvas_height(gui->canvas) - 2); |  | ||||||
|         canvas_draw_line( |         canvas_draw_line( | ||||||
|             gui->canvas, |             gui->canvas, | ||||||
|             2, |             canvas_width(gui->canvas) - 2, | ||||||
|  |             1, | ||||||
|  |             canvas_width(gui->canvas) - 2, | ||||||
|  |             canvas_height(gui->canvas) - 2); | ||||||
|  |         canvas_draw_line( | ||||||
|  |             gui->canvas, | ||||||
|  |             1, | ||||||
|             canvas_height(gui->canvas) - 2, |             canvas_height(gui->canvas) - 2, | ||||||
|             canvas_width(gui->canvas) - 2, |             canvas_width(gui->canvas) - 2, | ||||||
|             canvas_height(gui->canvas) - 2); |             canvas_height(gui->canvas) - 2); | ||||||
| 
 |  | ||||||
|         canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); |  | ||||||
| 
 |  | ||||||
|         canvas_set_color(gui->canvas, ColorWhite); |  | ||||||
|         canvas_draw_box(gui->canvas, 2, 1, width + 2, 10); |  | ||||||
|         canvas_set_color(gui->canvas, ColorBlack); |  | ||||||
| 
 |  | ||||||
|         canvas_frame_set( |  | ||||||
|             gui->canvas, x + 3, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); |  | ||||||
|         canvas_draw_icon(gui->canvas, 0, 0, &I_Attention_5x8); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -469,6 +494,7 @@ Gui* gui_alloc() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t gui_srv(void* p) { | int32_t gui_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     Gui* gui = gui_alloc(); |     Gui* gui = gui_alloc(); | ||||||
| 
 | 
 | ||||||
|     furi_record_create("gui", gui); |     furi_record_create("gui", gui); | ||||||
|  | |||||||
| @ -331,7 +331,7 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) { | |||||||
|             ButtonMenuItemArray_it_t it; |             ButtonMenuItemArray_it_t it; | ||||||
|             for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); |             for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); | ||||||
|                 ButtonMenuItemArray_next(it), ++item_position) { |                 ButtonMenuItemArray_next(it), ++item_position) { | ||||||
|                 if(ButtonMenuItemArray_cref(it)->index == index) { |                 if((uint32_t)ButtonMenuItemArray_cref(it)->index == index) { | ||||||
|                     model->position = item_position; |                     model->position = item_position; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|  | |||||||
| @ -215,8 +215,8 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
| static void button_panel_process_down(ButtonPanel* button_panel) { | static void button_panel_process_down(ButtonPanel* button_panel) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         button_panel->view, (ButtonPanelModel * model) { |         button_panel->view, (ButtonPanelModel * model) { | ||||||
|             size_t new_selected_item_x = model->selected_item_x; |             uint16_t new_selected_item_x = model->selected_item_x; | ||||||
|             size_t new_selected_item_y = model->selected_item_y; |             uint16_t new_selected_item_y = model->selected_item_y; | ||||||
|             size_t i; |             size_t i; | ||||||
| 
 | 
 | ||||||
|             if(new_selected_item_y >= (model->reserve_y - 1)) return false; |             if(new_selected_item_y >= (model->reserve_y - 1)) return false; | ||||||
| @ -291,8 +291,8 @@ static void button_panel_process_left(ButtonPanel* button_panel) { | |||||||
| static void button_panel_process_right(ButtonPanel* button_panel) { | static void button_panel_process_right(ButtonPanel* button_panel) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         button_panel->view, (ButtonPanelModel * model) { |         button_panel->view, (ButtonPanelModel * model) { | ||||||
|             size_t new_selected_item_x = model->selected_item_x; |             uint16_t new_selected_item_x = model->selected_item_x; | ||||||
|             size_t new_selected_item_y = model->selected_item_y; |             uint16_t new_selected_item_y = model->selected_item_y; | ||||||
|             size_t i; |             size_t i; | ||||||
| 
 | 
 | ||||||
|             if(new_selected_item_x >= (model->reserve_x - 1)) return false; |             if(new_selected_item_x >= (model->reserve_x - 1)) return false; | ||||||
|  | |||||||
| @ -6,10 +6,13 @@ struct EmptyScreen { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void empty_screen_view_draw_callback(Canvas* canvas, void* _model) { | static void empty_screen_view_draw_callback(Canvas* canvas, void* _model) { | ||||||
|  |     UNUSED(_model); | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool empty_screen_view_input_callback(InputEvent* event, void* context) { | static bool empty_screen_view_input_callback(InputEvent* event, void* context) { | ||||||
|  |     UNUSED(event); | ||||||
|  |     UNUSED(context); | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -34,6 +34,7 @@ static void loading_draw_callback(Canvas* canvas, void* _model) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool loading_input_callback(InputEvent* event, void* context) { | static bool loading_input_callback(InputEvent* event, void* context) { | ||||||
|  |     UNUSED(event); | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -87,7 +87,7 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { | |||||||
|         model->scroll_num = line_num - 4; |         model->scroll_num = line_num - 4; | ||||||
|         model->scroll_pos = line_num - 5; |         model->scroll_pos = line_num - 5; | ||||||
|     } else { |     } else { | ||||||
|         model->scroll_num = MAX(line_num - 4, 0); |         model->scroll_num = MAX(line_num - 4, 0u); | ||||||
|         model->scroll_pos = 0; |         model->scroll_pos = 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -122,15 +122,15 @@ static const TextInputKey* get_row(uint8_t row_index) { | |||||||
|     return row; |     return row; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char get_selected_char(TextInputModel* model) { | static char get_selected_char(TextInputModel* model) { | ||||||
|     return get_row(model->selected_row)[model->selected_column].text; |     return get_row(model->selected_row)[model->selected_column].text; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const bool char_is_lowercase(char letter) { | static bool char_is_lowercase(char letter) { | ||||||
|     return (letter >= 0x61 && letter <= 0x7A); |     return (letter >= 0x61 && letter <= 0x7A); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char char_to_uppercase(const char letter) { | static char char_to_uppercase(const char letter) { | ||||||
|     if(isalpha(letter)) { |     if(isalpha(letter)) { | ||||||
|         return (letter - 0x20); |         return (letter - 0x20); | ||||||
|     } else { |     } else { | ||||||
| @ -260,6 +260,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { | static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { | ||||||
|  |     UNUSED(text_input); | ||||||
|     if(model->selected_row > 0) { |     if(model->selected_row > 0) { | ||||||
|         model->selected_row--; |         model->selected_row--; | ||||||
|         if(model->selected_column > get_row_size(model->selected_row) - 6) { |         if(model->selected_column > get_row_size(model->selected_row) - 6) { | ||||||
| @ -269,6 +270,7 @@ static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void text_input_handle_down(TextInput* text_input, TextInputModel* model) { | static void text_input_handle_down(TextInput* text_input, TextInputModel* model) { | ||||||
|  |     UNUSED(text_input); | ||||||
|     if(model->selected_row < keyboard_row_count - 1) { |     if(model->selected_row < keyboard_row_count - 1) { | ||||||
|         model->selected_row++; |         model->selected_row++; | ||||||
|         if(model->selected_column > get_row_size(model->selected_row) - 4) { |         if(model->selected_column > get_row_size(model->selected_row) - 4) { | ||||||
| @ -278,6 +280,7 @@ static void text_input_handle_down(TextInput* text_input, TextInputModel* model) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void text_input_handle_left(TextInput* text_input, TextInputModel* model) { | static void text_input_handle_left(TextInput* text_input, TextInputModel* model) { | ||||||
|  |     UNUSED(text_input); | ||||||
|     if(model->selected_column > 0) { |     if(model->selected_column > 0) { | ||||||
|         model->selected_column--; |         model->selected_column--; | ||||||
|     } else { |     } else { | ||||||
| @ -286,6 +289,7 @@ static void text_input_handle_left(TextInput* text_input, TextInputModel* model) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void text_input_handle_right(TextInput* text_input, TextInputModel* model) { | static void text_input_handle_right(TextInput* text_input, TextInputModel* model) { | ||||||
|  |     UNUSED(text_input); | ||||||
|     if(model->selected_column < get_row_size(model->selected_row) - 1) { |     if(model->selected_column < get_row_size(model->selected_row) - 1) { | ||||||
|         model->selected_column++; |         model->selected_column++; | ||||||
|     } else { |     } else { | ||||||
|  | |||||||
| @ -364,6 +364,7 @@ void variable_item_list_set_enter_callback( | |||||||
|     furi_assert(callback); |     furi_assert(callback); | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         variable_item_list->view, (VariableItemListModel * model) { |         variable_item_list->view, (VariableItemListModel * model) { | ||||||
|  |             UNUSED(model); | ||||||
|             variable_item_list->callback = callback; |             variable_item_list->callback = callback; | ||||||
|             variable_item_list->context = context; |             variable_item_list->context = context; | ||||||
|             return false; |             return false; | ||||||
|  | |||||||
| @ -126,6 +126,7 @@ void view_commit_model(View* view, bool update) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void view_icon_animation_callback(IconAnimation* instance, void* context) { | void view_icon_animation_callback(IconAnimation* instance, void* context) { | ||||||
|  |     UNUSED(instance); | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     View* view = context; |     View* view = context; | ||||||
|     if(view->update_callback) { |     if(view->update_callback) { | ||||||
|  | |||||||
							
								
								
									
										349
									
								
								applications/ibutton/ibutton.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								applications/ibutton/ibutton.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,349 @@ | |||||||
|  | #include "ibutton.h" | ||||||
|  | #include "ibutton_i.h" | ||||||
|  | #include "ibutton/scenes/ibutton_scene.h" | ||||||
|  | 
 | ||||||
|  | #include <toolbox/path.h> | ||||||
|  | #include <flipper_format/flipper_format.h> | ||||||
|  | 
 | ||||||
|  | static const NotificationSequence* ibutton_notification_sequences[] = { | ||||||
|  |     &sequence_error, | ||||||
|  |     &sequence_success, | ||||||
|  |     &sequence_blink_cyan_10, | ||||||
|  |     &sequence_blink_magenta_10, | ||||||
|  |     &sequence_blink_yellow_10, | ||||||
|  |     &sequence_set_red_255, | ||||||
|  |     &sequence_reset_red, | ||||||
|  |     &sequence_set_green_255, | ||||||
|  |     &sequence_reset_green, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void ibutton_make_app_folder(iButton* ibutton) { | ||||||
|  |     if(!storage_simply_mkdir(ibutton->storage, IBUTTON_APP_FOLDER)) { | ||||||
|  |         dialog_message_show_storage_error(ibutton->dialogs, "Cannot create\napp folder"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool ibutton_load_key_data(iButton* ibutton, string_t key_path) { | ||||||
|  |     FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); | ||||||
|  |     bool result = false; | ||||||
|  |     string_t data; | ||||||
|  |     string_init(data); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break; | ||||||
|  | 
 | ||||||
|  |         // header
 | ||||||
|  |         uint32_t version; | ||||||
|  |         if(!flipper_format_read_header(file, data, &version)) break; | ||||||
|  |         if(string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break; | ||||||
|  |         if(version != 1) break; | ||||||
|  | 
 | ||||||
|  |         // key type
 | ||||||
|  |         iButtonKeyType type; | ||||||
|  |         if(!flipper_format_read_string(file, "Key type", data)) break; | ||||||
|  |         if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; | ||||||
|  | 
 | ||||||
|  |         // key data
 | ||||||
|  |         uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; | ||||||
|  |         if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         ibutton_key_set_type(ibutton->key, type); | ||||||
|  |         ibutton_key_set_data(ibutton->key, key_data, IBUTTON_KEY_DATA_SIZE); | ||||||
|  | 
 | ||||||
|  |         result = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     flipper_format_free(file); | ||||||
|  |     string_clear(data); | ||||||
|  | 
 | ||||||
|  |     if(!result) { | ||||||
|  |         dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_custom_event_callback(void* context, uint32_t event) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     iButton* ibutton = context; | ||||||
|  |     return scene_manager_handle_custom_event(ibutton->scene_manager, event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_back_event_callback(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     iButton* ibutton = context; | ||||||
|  |     return scene_manager_handle_back_event(ibutton->scene_manager); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_tick_event_callback(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     iButton* ibutton = context; | ||||||
|  |     scene_manager_handle_tick_event(ibutton->scene_manager); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | iButton* ibutton_alloc() { | ||||||
|  |     iButton* ibutton = malloc(sizeof(iButton)); | ||||||
|  | 
 | ||||||
|  |     ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton); | ||||||
|  | 
 | ||||||
|  |     ibutton->view_dispatcher = view_dispatcher_alloc(); | ||||||
|  |     view_dispatcher_enable_queue(ibutton->view_dispatcher); | ||||||
|  |     view_dispatcher_set_event_callback_context(ibutton->view_dispatcher, ibutton); | ||||||
|  |     view_dispatcher_set_custom_event_callback( | ||||||
|  |         ibutton->view_dispatcher, ibutton_custom_event_callback); | ||||||
|  |     view_dispatcher_set_navigation_event_callback( | ||||||
|  |         ibutton->view_dispatcher, ibutton_back_event_callback); | ||||||
|  |     view_dispatcher_set_tick_event_callback( | ||||||
|  |         ibutton->view_dispatcher, ibutton_tick_event_callback, 100); | ||||||
|  | 
 | ||||||
|  |     ibutton->gui = furi_record_open("gui"); | ||||||
|  |     view_dispatcher_attach_to_gui( | ||||||
|  |         ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); | ||||||
|  | 
 | ||||||
|  |     ibutton->storage = furi_record_open("storage"); | ||||||
|  |     ibutton->dialogs = furi_record_open("dialogs"); | ||||||
|  |     ibutton->notifications = furi_record_open("notification"); | ||||||
|  | 
 | ||||||
|  |     ibutton->key = ibutton_key_alloc(); | ||||||
|  |     ibutton->key_worker = ibutton_worker_alloc(); | ||||||
|  |     ibutton_worker_start_thread(ibutton->key_worker); | ||||||
|  | 
 | ||||||
|  |     ibutton->submenu = submenu_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewSubmenu, submenu_get_view(ibutton->submenu)); | ||||||
|  | 
 | ||||||
|  |     ibutton->byte_input = byte_input_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewByteInput, byte_input_get_view(ibutton->byte_input)); | ||||||
|  | 
 | ||||||
|  |     ibutton->text_input = text_input_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewTextInput, text_input_get_view(ibutton->text_input)); | ||||||
|  | 
 | ||||||
|  |     ibutton->popup = popup_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewPopup, popup_get_view(ibutton->popup)); | ||||||
|  | 
 | ||||||
|  |     ibutton->widget = widget_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget)); | ||||||
|  | 
 | ||||||
|  |     ibutton->dialog_ex = dialog_ex_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         ibutton->view_dispatcher, iButtonViewDialogEx, dialog_ex_get_view(ibutton->dialog_ex)); | ||||||
|  | 
 | ||||||
|  |     return ibutton; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_free(iButton* ibutton) { | ||||||
|  |     furi_assert(ibutton); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewDialogEx); | ||||||
|  |     dialog_ex_free(ibutton->dialog_ex); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget); | ||||||
|  |     widget_free(ibutton->widget); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewPopup); | ||||||
|  |     popup_free(ibutton->popup); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewTextInput); | ||||||
|  |     text_input_free(ibutton->text_input); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewByteInput); | ||||||
|  |     byte_input_free(ibutton->byte_input); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewSubmenu); | ||||||
|  |     submenu_free(ibutton->submenu); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_free(ibutton->view_dispatcher); | ||||||
|  |     scene_manager_free(ibutton->scene_manager); | ||||||
|  | 
 | ||||||
|  |     furi_record_close("storage"); | ||||||
|  |     ibutton->storage = NULL; | ||||||
|  | 
 | ||||||
|  |     furi_record_close("notification"); | ||||||
|  |     ibutton->notifications = NULL; | ||||||
|  | 
 | ||||||
|  |     furi_record_close("dialogs"); | ||||||
|  |     ibutton->dialogs = NULL; | ||||||
|  | 
 | ||||||
|  |     furi_record_close("gui"); | ||||||
|  |     ibutton->gui = NULL; | ||||||
|  | 
 | ||||||
|  |     ibutton_worker_stop_thread(ibutton->key_worker); | ||||||
|  |     ibutton_worker_free(ibutton->key_worker); | ||||||
|  |     ibutton_key_free(ibutton->key); | ||||||
|  | 
 | ||||||
|  |     free(ibutton); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_file_select(iButton* ibutton) { | ||||||
|  |     bool success = dialog_file_select_show( | ||||||
|  |         ibutton->dialogs, | ||||||
|  |         IBUTTON_APP_FOLDER, | ||||||
|  |         IBUTTON_APP_EXTENSION, | ||||||
|  |         ibutton->file_name, | ||||||
|  |         IBUTTON_FILE_NAME_SIZE, | ||||||
|  |         ibutton_key_get_name_p(ibutton->key)); | ||||||
|  | 
 | ||||||
|  |     if(success) { | ||||||
|  |         string_t key_str; | ||||||
|  |         string_init_printf( | ||||||
|  |             key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION); | ||||||
|  |         success = ibutton_load_key_data(ibutton, key_str); | ||||||
|  | 
 | ||||||
|  |         if(success) { | ||||||
|  |             ibutton_key_set_name(ibutton->key, ibutton->file_name); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         string_clear(key_str); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_load_key(iButton* ibutton, const char* key_name) { | ||||||
|  |     string_t key_path; | ||||||
|  |     string_init_set_str(key_path, key_name); | ||||||
|  | 
 | ||||||
|  |     const bool success = ibutton_load_key_data(ibutton, key_path); | ||||||
|  | 
 | ||||||
|  |     if(success) { | ||||||
|  |         path_extract_filename_no_ext(key_name, key_path); | ||||||
|  |         ibutton_key_set_name(ibutton->key, string_get_cstr(key_path)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     string_clear(key_path); | ||||||
|  |     return success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_save_key(iButton* ibutton, const char* key_name) { | ||||||
|  |     // Create ibutton directory if necessary
 | ||||||
|  |     ibutton_make_app_folder(ibutton); | ||||||
|  | 
 | ||||||
|  |     FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); | ||||||
|  |     iButtonKey* key = ibutton->key; | ||||||
|  | 
 | ||||||
|  |     string_t key_file_name; | ||||||
|  |     bool result = false; | ||||||
|  |     string_init(key_file_name); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // First remove key if it was saved (we rename the key)
 | ||||||
|  |         if(!ibutton_delete_key(ibutton)) break; | ||||||
|  | 
 | ||||||
|  |         // Save the key
 | ||||||
|  |         ibutton_key_set_name(key, key_name); | ||||||
|  | 
 | ||||||
|  |         // Set full file name, for new key
 | ||||||
|  |         string_printf( | ||||||
|  |             key_file_name, | ||||||
|  |             "%s/%s%s", | ||||||
|  |             IBUTTON_APP_FOLDER, | ||||||
|  |             ibutton_key_get_name_p(key), | ||||||
|  |             IBUTTON_APP_EXTENSION); | ||||||
|  | 
 | ||||||
|  |         // Open file for write
 | ||||||
|  |         if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; | ||||||
|  | 
 | ||||||
|  |         // Write header
 | ||||||
|  |         if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break; | ||||||
|  | 
 | ||||||
|  |         // Write key type
 | ||||||
|  |         if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) | ||||||
|  |             break; | ||||||
|  |         const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); | ||||||
|  |         if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; | ||||||
|  | 
 | ||||||
|  |         // Write data
 | ||||||
|  |         if(!flipper_format_write_comment_cstr( | ||||||
|  |                file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         if(!flipper_format_write_hex( | ||||||
|  |                file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) | ||||||
|  |             break; | ||||||
|  |         result = true; | ||||||
|  | 
 | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     flipper_format_free(file); | ||||||
|  | 
 | ||||||
|  |     string_clear(key_file_name); | ||||||
|  | 
 | ||||||
|  |     if(!result) { | ||||||
|  |         dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ibutton_delete_key(iButton* ibutton) { | ||||||
|  |     string_t file_name; | ||||||
|  |     bool result = false; | ||||||
|  | 
 | ||||||
|  |     string_init_printf( | ||||||
|  |         file_name, | ||||||
|  |         "%s/%s%s", | ||||||
|  |         IBUTTON_APP_FOLDER, | ||||||
|  |         ibutton_key_get_name_p(ibutton->key), | ||||||
|  |         IBUTTON_APP_EXTENSION); | ||||||
|  |     result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name)); | ||||||
|  |     string_clear(file_name); | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_text_store_set(iButton* ibutton, const char* text, ...) { | ||||||
|  |     va_list args; | ||||||
|  |     va_start(args, text); | ||||||
|  | 
 | ||||||
|  |     vsnprintf(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE, text, args); | ||||||
|  | 
 | ||||||
|  |     va_end(args); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_text_store_clear(iButton* ibutton) { | ||||||
|  |     memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_switch_to_previous_scene_one_of( | ||||||
|  |     iButton* ibutton, | ||||||
|  |     const uint32_t* scene_ids, | ||||||
|  |     size_t scene_ids_size) { | ||||||
|  |     furi_assert(scene_ids_size); | ||||||
|  |     SceneManager* scene_manager = ibutton->scene_manager; | ||||||
|  | 
 | ||||||
|  |     for(size_t i = 0; i < scene_ids_size; ++i) { | ||||||
|  |         const uint32_t scene_id = scene_ids[i]; | ||||||
|  |         if(scene_manager_has_previous_scene(scene_manager, scene_id)) { | ||||||
|  |             scene_manager_search_and_switch_to_previous_scene(scene_manager, scene_id); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_notification_message(iButton* ibutton, uint32_t message) { | ||||||
|  |     furi_assert(message < sizeof(ibutton_notification_sequences) / sizeof(NotificationSequence*)); | ||||||
|  |     notification_message(ibutton->notifications, ibutton_notification_sequences[message]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ibutton_app(void* p) { | ||||||
|  |     iButton* ibutton = ibutton_alloc(); | ||||||
|  | 
 | ||||||
|  |     ibutton_make_app_folder(ibutton); | ||||||
|  | 
 | ||||||
|  |     if(p && ibutton_load_key(ibutton, (const char*)p)) { | ||||||
|  |         // TODO: Display an error if the key from p could not be loaded
 | ||||||
|  |         scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); | ||||||
|  |     } else { | ||||||
|  |         scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_run(ibutton->view_dispatcher); | ||||||
|  | 
 | ||||||
|  |     ibutton_free(ibutton); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -1,10 +0,0 @@ | |||||||
| #include "ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| // app enter function
 |  | ||||||
| extern "C" int32_t ibutton_app(void* p) { |  | ||||||
|     iButtonApp* app = new iButtonApp(); |  | ||||||
|     app->run(p); |  | ||||||
|     delete app; |  | ||||||
| 
 |  | ||||||
|     return 255; |  | ||||||
| } |  | ||||||
							
								
								
									
										3
									
								
								applications/ibutton/ibutton.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								applications/ibutton/ibutton.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | typedef struct iButton iButton; | ||||||
| @ -1,342 +0,0 @@ | |||||||
| #include "ibutton_app.h" |  | ||||||
| #include <stdarg.h> |  | ||||||
| #include <furi_hal.h> |  | ||||||
| #include <m-string.h> |  | ||||||
| #include <toolbox/path.h> |  | ||||||
| #include <flipper_format/flipper_format.h> |  | ||||||
| 
 |  | ||||||
| const char* iButtonApp::app_folder = "/any/ibutton"; |  | ||||||
| const char* iButtonApp::app_extension = ".ibtn"; |  | ||||||
| const char* iButtonApp::app_filetype = "Flipper iButton key"; |  | ||||||
| 
 |  | ||||||
| void iButtonApp::run(void* args) { |  | ||||||
|     iButtonEvent event; |  | ||||||
|     bool consumed; |  | ||||||
|     bool exit = false; |  | ||||||
| 
 |  | ||||||
|     make_app_folder(); |  | ||||||
| 
 |  | ||||||
|     if(args && load_key((const char*)args)) { |  | ||||||
|         current_scene = Scene::SceneEmulate; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     scenes[current_scene]->on_enter(this); |  | ||||||
| 
 |  | ||||||
|     while(!exit) { |  | ||||||
|         view.receive_event(&event); |  | ||||||
| 
 |  | ||||||
|         consumed = scenes[current_scene]->on_event(this, &event); |  | ||||||
| 
 |  | ||||||
|         if(!consumed) { |  | ||||||
|             if(event.type == iButtonEvent::Type::EventTypeBack) { |  | ||||||
|                 exit = switch_to_previous_scene(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     scenes[current_scene]->on_exit(this); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonApp::iButtonApp() |  | ||||||
|     : notification{"notification"} |  | ||||||
|     , storage{"storage"} |  | ||||||
|     , dialogs{"dialogs"} { |  | ||||||
|     key = ibutton_key_alloc(); |  | ||||||
|     key_worker = ibutton_worker_alloc(); |  | ||||||
|     ibutton_worker_start_thread(key_worker); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonApp::~iButtonApp() { |  | ||||||
|     for(std::map<Scene, iButtonScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) { |  | ||||||
|         delete it->second; |  | ||||||
|     } |  | ||||||
|     scenes.clear(); |  | ||||||
| 
 |  | ||||||
|     ibutton_worker_stop_thread(key_worker); |  | ||||||
|     ibutton_worker_free(key_worker); |  | ||||||
|     ibutton_key_free(key); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonAppViewManager* iButtonApp::get_view_manager() { |  | ||||||
|     return &view; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::switch_to_next_scene(Scene next_scene) { |  | ||||||
|     previous_scenes_list.push_front(current_scene); |  | ||||||
| 
 |  | ||||||
|     if(next_scene != Scene::SceneExit) { |  | ||||||
|         scenes[current_scene]->on_exit(this); |  | ||||||
|         current_scene = next_scene; |  | ||||||
|         scenes[current_scene]->on_enter(this); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) { |  | ||||||
|     Scene previous_scene = Scene::SceneStart; |  | ||||||
|     bool scene_found = false; |  | ||||||
| 
 |  | ||||||
|     while(!scene_found) { |  | ||||||
|         previous_scene = get_previous_scene(); |  | ||||||
|         for(Scene element : scenes_list) { |  | ||||||
|             if(previous_scene == element || previous_scene == Scene::SceneStart) { |  | ||||||
|                 scene_found = true; |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     scenes[current_scene]->on_exit(this); |  | ||||||
|     current_scene = previous_scene; |  | ||||||
|     scenes[current_scene]->on_enter(this); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonApp::switch_to_previous_scene(uint8_t count) { |  | ||||||
|     Scene previous_scene = Scene::SceneStart; |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < count; i++) { |  | ||||||
|         previous_scene = get_previous_scene(); |  | ||||||
|         if(previous_scene == Scene::SceneExit) break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(previous_scene == Scene::SceneExit) { |  | ||||||
|         return true; |  | ||||||
|     } else { |  | ||||||
|         scenes[current_scene]->on_exit(this); |  | ||||||
|         current_scene = previous_scene; |  | ||||||
|         scenes[current_scene]->on_enter(this); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonApp::Scene iButtonApp::get_previous_scene() { |  | ||||||
|     Scene scene = previous_scenes_list.front(); |  | ||||||
|     previous_scenes_list.pop_front(); |  | ||||||
|     return scene; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonWorker* iButtonApp::get_key_worker() { |  | ||||||
|     return key_worker; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonKey* iButtonApp::get_key() { |  | ||||||
|     return key; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char* iButtonApp::get_file_name() { |  | ||||||
|     return file_name; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t iButtonApp::get_file_name_size() { |  | ||||||
|     return file_name_size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_read() { |  | ||||||
|     notification_message(notification, &sequence_blink_cyan_10); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_emulate() { |  | ||||||
|     notification_message(notification, &sequence_blink_magenta_10); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_yellow_blink() { |  | ||||||
|     notification_message(notification, &sequence_blink_yellow_10); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_error() { |  | ||||||
|     notification_message(notification, &sequence_error); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_success() { |  | ||||||
|     notification_message(notification, &sequence_success); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_green_on() { |  | ||||||
|     notification_message_block(notification, &sequence_set_green_255); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_green_off() { |  | ||||||
|     notification_message(notification, &sequence_reset_green); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_red_on() { |  | ||||||
|     notification_message_block(notification, &sequence_set_red_255); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::notify_red_off() { |  | ||||||
|     notification_message(notification, &sequence_reset_red); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::set_text_store(const char* text...) { |  | ||||||
|     va_list args; |  | ||||||
|     va_start(args, text); |  | ||||||
| 
 |  | ||||||
|     vsnprintf(text_store, text_store_size, text, args); |  | ||||||
| 
 |  | ||||||
|     va_end(args); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char* iButtonApp::get_text_store() { |  | ||||||
|     return text_store; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t iButtonApp::get_text_store_size() { |  | ||||||
|     return text_store_size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // file managment
 |  | ||||||
| bool iButtonApp::save_key(const char* key_name) { |  | ||||||
|     // Create ibutton directory if necessary
 |  | ||||||
|     make_app_folder(); |  | ||||||
| 
 |  | ||||||
|     FlipperFormat* file = flipper_format_file_alloc(storage); |  | ||||||
|     string_t key_file_name; |  | ||||||
|     bool result = false; |  | ||||||
|     string_init(key_file_name); |  | ||||||
| 
 |  | ||||||
|     do { |  | ||||||
|         // First remove key if it was saved (we rename the key)
 |  | ||||||
|         if(!delete_key()) break; |  | ||||||
| 
 |  | ||||||
|         // Save the key
 |  | ||||||
|         ibutton_key_set_name(key, key_name); |  | ||||||
| 
 |  | ||||||
|         // Set full file name, for new key
 |  | ||||||
|         string_printf( |  | ||||||
|             key_file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); |  | ||||||
| 
 |  | ||||||
|         // Open file for write
 |  | ||||||
|         if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; |  | ||||||
| 
 |  | ||||||
|         // Write header
 |  | ||||||
|         if(!flipper_format_write_header_cstr(file, iButtonApp::app_filetype, 1)) break; |  | ||||||
| 
 |  | ||||||
|         // Write key type
 |  | ||||||
|         if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) |  | ||||||
|             break; |  | ||||||
|         const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); |  | ||||||
|         if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; |  | ||||||
| 
 |  | ||||||
|         // Write data
 |  | ||||||
|         if(!flipper_format_write_comment_cstr( |  | ||||||
|                file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         if(!flipper_format_write_hex( |  | ||||||
|                file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) |  | ||||||
|             break; |  | ||||||
|         result = true; |  | ||||||
| 
 |  | ||||||
|     } while(false); |  | ||||||
| 
 |  | ||||||
|     flipper_format_free(file); |  | ||||||
| 
 |  | ||||||
|     string_clear(key_file_name); |  | ||||||
| 
 |  | ||||||
|     if(!result) { |  | ||||||
|         dialog_message_show_storage_error(dialogs, "Cannot save\nkey file"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonApp::load_key_data(string_t key_path) { |  | ||||||
|     FlipperFormat* file = flipper_format_file_alloc(storage); |  | ||||||
|     bool result = false; |  | ||||||
|     string_t data; |  | ||||||
|     string_init(data); |  | ||||||
| 
 |  | ||||||
|     do { |  | ||||||
|         if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break; |  | ||||||
| 
 |  | ||||||
|         // header
 |  | ||||||
|         uint32_t version; |  | ||||||
|         if(!flipper_format_read_header(file, data, &version)) break; |  | ||||||
|         if(string_cmp_str(data, iButtonApp::app_filetype) != 0) break; |  | ||||||
|         if(version != 1) break; |  | ||||||
| 
 |  | ||||||
|         // key type
 |  | ||||||
|         iButtonKeyType type; |  | ||||||
|         if(!flipper_format_read_string(file, "Key type", data)) break; |  | ||||||
|         if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; |  | ||||||
| 
 |  | ||||||
|         // key data
 |  | ||||||
|         uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; |  | ||||||
|         if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         ibutton_key_set_type(key, type); |  | ||||||
|         ibutton_key_set_data(key, key_data, IBUTTON_KEY_DATA_SIZE); |  | ||||||
| 
 |  | ||||||
|         result = true; |  | ||||||
|     } while(false); |  | ||||||
| 
 |  | ||||||
|     flipper_format_free(file); |  | ||||||
|     string_clear(data); |  | ||||||
| 
 |  | ||||||
|     if(!result) { |  | ||||||
|         dialog_message_show_storage_error(dialogs, "Cannot load\nkey file"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonApp::load_key(const char* key_name) { |  | ||||||
|     bool result = false; |  | ||||||
|     string_t key_path; |  | ||||||
| 
 |  | ||||||
|     string_init_set_str(key_path, key_name); |  | ||||||
| 
 |  | ||||||
|     result = load_key_data(key_path); |  | ||||||
|     if(result) { |  | ||||||
|         path_extract_filename_no_ext(key_name, key_path); |  | ||||||
|         ibutton_key_set_name(key, string_get_cstr(key_path)); |  | ||||||
|     } |  | ||||||
|     string_clear(key_path); |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonApp::load_key() { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     // Input events and views are managed by file_select
 |  | ||||||
|     bool res = dialog_file_select_show( |  | ||||||
|         dialogs, |  | ||||||
|         app_folder, |  | ||||||
|         app_extension, |  | ||||||
|         get_file_name(), |  | ||||||
|         get_file_name_size(), |  | ||||||
|         ibutton_key_get_name_p(key)); |  | ||||||
| 
 |  | ||||||
|     if(res) { |  | ||||||
|         string_t key_str; |  | ||||||
| 
 |  | ||||||
|         // Get key file path
 |  | ||||||
|         string_init_printf(key_str, "%s/%s%s", app_folder, get_file_name(), app_extension); |  | ||||||
| 
 |  | ||||||
|         result = load_key_data(key_str); |  | ||||||
|         if(result) { |  | ||||||
|             ibutton_key_set_name(key, get_file_name()); |  | ||||||
|         } |  | ||||||
|         string_clear(key_str); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonApp::delete_key() { |  | ||||||
|     string_t file_name; |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     string_init_printf( |  | ||||||
|         file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); |  | ||||||
|     result = storage_simply_remove(storage, string_get_cstr(file_name)); |  | ||||||
|     string_clear(file_name); |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonApp::make_app_folder() { |  | ||||||
|     if(!storage_simply_mkdir(storage, app_folder)) { |  | ||||||
|         dialog_message_show_storage_error(dialogs, "Cannot create\napp folder"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,144 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <map> |  | ||||||
| #include <list> |  | ||||||
| 
 |  | ||||||
| #include "ibutton_view_manager.h" |  | ||||||
| #include "scene/ibutton_scene_generic.h" |  | ||||||
| #include "scene/ibutton_scene_start.h" |  | ||||||
| #include "scene/ibutton_scene_read.h" |  | ||||||
| #include "scene/ibutton_scene_read_crc_error.h" |  | ||||||
| #include "scene/ibutton_scene_read_not_key_error.h" |  | ||||||
| #include "scene/ibutton_scene_read_success.h" |  | ||||||
| #include "scene/ibutton_scene_retry_confirm.h" |  | ||||||
| #include "scene/ibutton_scene_exit_confirm.h" |  | ||||||
| #include "scene/ibutton_scene_read_key_menu.h" |  | ||||||
| #include "scene/ibutton_scene_write.h" |  | ||||||
| #include "scene/ibutton_scene_write_success.h" |  | ||||||
| #include "scene/ibutton_scene_saved_key_menu.h" |  | ||||||
| #include "scene/ibutton_scene_delete_confirm.h" |  | ||||||
| #include "scene/ibutton_scene_delete_success.h" |  | ||||||
| #include "scene/ibutton_scene_emulate.h" |  | ||||||
| #include "scene/ibutton_scene_save_name.h" |  | ||||||
| #include "scene/ibutton_scene_save_success.h" |  | ||||||
| #include "scene/ibutton_scene_info.h" |  | ||||||
| #include "scene/ibutton_scene_select_key.h" |  | ||||||
| #include "scene/ibutton_scene_add_type.h" |  | ||||||
| #include "scene/ibutton_scene_add_value.h" |  | ||||||
| #include <one_wire/ibutton/ibutton_worker.h> |  | ||||||
| #include <notification/notification_messages.h> |  | ||||||
| #include <storage/storage.h> |  | ||||||
| #include <dialogs/dialogs.h> |  | ||||||
| #include <record_controller.hpp> |  | ||||||
| 
 |  | ||||||
| class iButtonApp { |  | ||||||
| public: |  | ||||||
|     void run(void* args); |  | ||||||
| 
 |  | ||||||
|     iButtonApp(); |  | ||||||
|     ~iButtonApp(); |  | ||||||
| 
 |  | ||||||
|     enum class Scene : uint8_t { |  | ||||||
|         SceneExit, |  | ||||||
|         SceneStart, |  | ||||||
|         SceneRead, |  | ||||||
|         SceneReadNotKeyError, |  | ||||||
|         SceneReadCRCError, |  | ||||||
|         SceneReadSuccess, |  | ||||||
|         SceneRetryConfirm, |  | ||||||
|         SceneExitConfirm, |  | ||||||
|         SceneReadKeyMenu, |  | ||||||
|         SceneWrite, |  | ||||||
|         SceneWriteSuccess, |  | ||||||
|         SceneEmulate, |  | ||||||
|         SceneSavedKeyMenu, |  | ||||||
|         SceneDeleteConfirm, |  | ||||||
|         SceneDeleteSuccess, |  | ||||||
|         SceneSaveName, |  | ||||||
|         SceneSaveSuccess, |  | ||||||
|         SceneInfo, |  | ||||||
|         SceneSelectKey, |  | ||||||
|         SceneAddType, |  | ||||||
|         SceneAddValue, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     static const char* app_folder; |  | ||||||
|     static const char* app_extension; |  | ||||||
|     static const char* app_filetype; |  | ||||||
| 
 |  | ||||||
|     iButtonAppViewManager* get_view_manager(); |  | ||||||
|     void switch_to_next_scene(Scene index); |  | ||||||
|     void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list); |  | ||||||
|     bool switch_to_previous_scene(uint8_t count = 1); |  | ||||||
|     Scene get_previous_scene(); |  | ||||||
| 
 |  | ||||||
|     const GpioPin* get_ibutton_pin(); |  | ||||||
|     iButtonWorker* get_key_worker(); |  | ||||||
|     iButtonKey* get_key(); |  | ||||||
| 
 |  | ||||||
|     void notify_read(); |  | ||||||
|     void notify_yellow_blink(); |  | ||||||
|     void notify_emulate(); |  | ||||||
| 
 |  | ||||||
|     void notify_error(); |  | ||||||
|     void notify_success(); |  | ||||||
|     void notify_green_on(); |  | ||||||
|     void notify_green_off(); |  | ||||||
|     void notify_red_on(); |  | ||||||
|     void notify_red_off(); |  | ||||||
| 
 |  | ||||||
|     void set_text_store(const char* text...); |  | ||||||
|     char* get_text_store(); |  | ||||||
|     uint8_t get_text_store_size(); |  | ||||||
| 
 |  | ||||||
|     char* get_file_name(); |  | ||||||
|     uint8_t get_file_name_size(); |  | ||||||
| 
 |  | ||||||
|     bool save_key(const char* key_name); |  | ||||||
|     bool load_key(); |  | ||||||
|     bool load_key(const char* key_name); |  | ||||||
|     bool delete_key(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     std::list<Scene> previous_scenes_list = {Scene::SceneExit}; |  | ||||||
|     Scene current_scene = Scene::SceneStart; |  | ||||||
|     iButtonAppViewManager view; |  | ||||||
| 
 |  | ||||||
|     std::map<Scene, iButtonScene*> scenes = { |  | ||||||
|         {Scene::SceneStart, new iButtonSceneStart()}, |  | ||||||
|         {Scene::SceneRead, new iButtonSceneRead()}, |  | ||||||
|         {Scene::SceneReadCRCError, new iButtonSceneReadCRCError()}, |  | ||||||
|         {Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()}, |  | ||||||
|         {Scene::SceneReadSuccess, new iButtonSceneReadSuccess()}, |  | ||||||
|         {Scene::SceneRetryConfirm, new iButtonSceneRetryConfirm()}, |  | ||||||
|         {Scene::SceneExitConfirm, new iButtonSceneExitConfirm()}, |  | ||||||
|         {Scene::SceneReadKeyMenu, new iButtonSceneReadKeyMenu()}, |  | ||||||
|         {Scene::SceneWrite, new iButtonSceneWrite()}, |  | ||||||
|         {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, |  | ||||||
|         {Scene::SceneEmulate, new iButtonSceneEmulate()}, |  | ||||||
|         {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, |  | ||||||
|         {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, |  | ||||||
|         {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, |  | ||||||
|         {Scene::SceneSaveName, new iButtonSceneSaveName()}, |  | ||||||
|         {Scene::SceneSaveSuccess, new iButtonSceneSaveSuccess()}, |  | ||||||
|         {Scene::SceneInfo, new iButtonSceneInfo()}, |  | ||||||
|         {Scene::SceneSelectKey, new iButtonSceneSelectKey()}, |  | ||||||
|         {Scene::SceneAddType, new iButtonSceneAddType()}, |  | ||||||
|         {Scene::SceneAddValue, new iButtonSceneAddValue()}, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     iButtonWorker* key_worker; |  | ||||||
|     iButtonKey* key; |  | ||||||
| 
 |  | ||||||
|     RecordController<NotificationApp> notification; |  | ||||||
|     RecordController<Storage> storage; |  | ||||||
|     RecordController<DialogsApp> dialogs; |  | ||||||
| 
 |  | ||||||
|     static const uint8_t file_name_size = 100; |  | ||||||
|     char file_name[file_name_size]; |  | ||||||
| 
 |  | ||||||
|     static const uint8_t text_store_size = 128; |  | ||||||
|     char text_store[text_store_size + 1]; |  | ||||||
| 
 |  | ||||||
|     bool load_key_data(string_t key_path); |  | ||||||
|     void make_app_folder(); |  | ||||||
| }; |  | ||||||
| @ -240,6 +240,7 @@ void ibutton_cli_emulate(Cli* cli, string_t args) { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void ibutton_cli(Cli* cli, string_t args, void* context) { | static void ibutton_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     string_t cmd; |     string_t cmd; | ||||||
|     string_init(cmd); |     string_init(cmd); | ||||||
| 
 | 
 | ||||||
| @ -268,6 +269,7 @@ void onewire_cli_print_usage() { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void onewire_cli_search(Cli* cli) { | static void onewire_cli_search(Cli* cli) { | ||||||
|  |     UNUSED(cli); | ||||||
|     OneWireHost* onewire = onewire_host_alloc(); |     OneWireHost* onewire = onewire_host_alloc(); | ||||||
|     uint8_t address[8]; |     uint8_t address[8]; | ||||||
|     bool done = false; |     bool done = false; | ||||||
| @ -297,6 +299,7 @@ static void onewire_cli_search(Cli* cli) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void onewire_cli(Cli* cli, string_t args, void* context) { | void onewire_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|     string_t cmd; |     string_t cmd; | ||||||
|     string_init(cmd); |     string_init(cmd); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								applications/ibutton/ibutton_custom_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/ibutton/ibutton_custom_event.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | enum iButtonCustomEvent { | ||||||
|  |     // Reserve first 100 events for button types and indexes, starting from 0
 | ||||||
|  |     iButtonCustomEventReserved = 100, | ||||||
|  | 
 | ||||||
|  |     iButtonCustomEventBack, | ||||||
|  |     iButtonCustomEventTextEditResult, | ||||||
|  |     iButtonCustomEventByteEditResult, | ||||||
|  |     iButtonCustomEventWorkerEmulated, | ||||||
|  |     iButtonCustomEventWorkerRead, | ||||||
|  | }; | ||||||
| @ -1,35 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <gui/modules/dialog_ex.h> |  | ||||||
| #include <gui/modules/widget.h> |  | ||||||
| #include <one_wire/ibutton/ibutton_worker.h> |  | ||||||
| 
 |  | ||||||
| class iButtonApp; |  | ||||||
| 
 |  | ||||||
| class iButtonEvent { |  | ||||||
| public: |  | ||||||
|     // events enum
 |  | ||||||
|     enum class Type : uint8_t { |  | ||||||
|         EventTypeTick, |  | ||||||
|         EventTypeBack, |  | ||||||
|         EventTypeMenuSelected, |  | ||||||
|         EventTypeDialogResult, |  | ||||||
|         EventTypeTextEditResult, |  | ||||||
|         EventTypeByteEditResult, |  | ||||||
|         EventTypeWidgetButtonResult, |  | ||||||
|         EventTypeWorkerEmulated, |  | ||||||
|         EventTypeWorkerRead, |  | ||||||
|         EventTypeWorkerWrite, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     // payload
 |  | ||||||
|     union { |  | ||||||
|         uint32_t menu_index; |  | ||||||
|         DialogExResult dialog_result; |  | ||||||
|         GuiButtonType widget_button_result; |  | ||||||
|         iButtonWorkerWriteResult worker_write_result; |  | ||||||
|     } payload; |  | ||||||
| 
 |  | ||||||
|     // event type
 |  | ||||||
|     Type type; |  | ||||||
| }; |  | ||||||
							
								
								
									
										86
									
								
								applications/ibutton/ibutton_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								applications/ibutton/ibutton_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "ibutton.h" | ||||||
|  | 
 | ||||||
|  | #include <gui/gui.h> | ||||||
|  | #include <gui/view.h> | ||||||
|  | #include <gui/view_dispatcher.h> | ||||||
|  | #include <gui/scene_manager.h> | ||||||
|  | #include <notification/notification_messages.h> | ||||||
|  | 
 | ||||||
|  | #include <one_wire/ibutton/ibutton_worker.h> | ||||||
|  | #include <storage/storage.h> | ||||||
|  | #include <dialogs/dialogs.h> | ||||||
|  | 
 | ||||||
|  | #include <gui/modules/submenu.h> | ||||||
|  | #include <gui/modules/popup.h> | ||||||
|  | #include <gui/modules/dialog_ex.h> | ||||||
|  | #include <gui/modules/text_input.h> | ||||||
|  | #include <gui/modules/byte_input.h> | ||||||
|  | #include <gui/modules/widget.h> | ||||||
|  | 
 | ||||||
|  | #include "ibutton_custom_event.h" | ||||||
|  | #include "scenes/ibutton_scene.h" | ||||||
|  | 
 | ||||||
|  | #define IBUTTON_FILE_NAME_SIZE 100 | ||||||
|  | #define IBUTTON_TEXT_STORE_SIZE 128 | ||||||
|  | 
 | ||||||
|  | #define IBUTTON_APP_FOLDER "/any/ibutton" | ||||||
|  | #define IBUTTON_APP_EXTENSION ".ibtn" | ||||||
|  | #define IBUTTON_APP_FILE_TYPE "Flipper iButton key" | ||||||
|  | 
 | ||||||
|  | struct iButton { | ||||||
|  |     SceneManager* scene_manager; | ||||||
|  |     ViewDispatcher* view_dispatcher; | ||||||
|  | 
 | ||||||
|  |     Gui* gui; | ||||||
|  |     Storage* storage; | ||||||
|  |     DialogsApp* dialogs; | ||||||
|  |     NotificationApp* notifications; | ||||||
|  | 
 | ||||||
|  |     iButtonWorker* key_worker; | ||||||
|  |     iButtonKey* key; | ||||||
|  | 
 | ||||||
|  |     char file_name[IBUTTON_FILE_NAME_SIZE]; | ||||||
|  |     char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; | ||||||
|  | 
 | ||||||
|  |     Submenu* submenu; | ||||||
|  |     ByteInput* byte_input; | ||||||
|  |     TextInput* text_input; | ||||||
|  |     Popup* popup; | ||||||
|  |     Widget* widget; | ||||||
|  |     DialogEx* dialog_ex; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     iButtonViewSubmenu, | ||||||
|  |     iButtonViewByteInput, | ||||||
|  |     iButtonViewTextInput, | ||||||
|  |     iButtonViewPopup, | ||||||
|  |     iButtonViewWidget, | ||||||
|  |     iButtonViewDialogEx, | ||||||
|  | } iButtonView; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     iButtonNotificationMessageError, | ||||||
|  |     iButtonNotificationMessageSuccess, | ||||||
|  |     iButtonNotificationMessageRead, | ||||||
|  |     iButtonNotificationMessageEmulate, | ||||||
|  |     iButtonNotificationMessageYellowBlink, | ||||||
|  |     iButtonNotificationMessageRedOn, | ||||||
|  |     iButtonNotificationMessageRedOff, | ||||||
|  |     iButtonNotificationMessageGreenOn, | ||||||
|  |     iButtonNotificationMessageGreenOff, | ||||||
|  | } iButtonNotificationMessage; | ||||||
|  | 
 | ||||||
|  | bool ibutton_file_select(iButton* ibutton); | ||||||
|  | bool ibutton_load_key(iButton* ibutton, const char* key_name); | ||||||
|  | bool ibutton_save_key(iButton* ibutton, const char* key_name); | ||||||
|  | bool ibutton_delete_key(iButton* ibutton); | ||||||
|  | void ibutton_text_store_set(iButton* ibutton, const char* text, ...); | ||||||
|  | void ibutton_text_store_clear(iButton* ibutton); | ||||||
|  | void ibutton_switch_to_previous_scene_one_of( | ||||||
|  |     iButton* ibutton, | ||||||
|  |     const uint32_t* scene_ids, | ||||||
|  |     size_t scene_ids_size); | ||||||
|  | void ibutton_notification_message(iButton* ibutton, uint32_t message); | ||||||
| @ -1,140 +0,0 @@ | |||||||
| #include "ibutton_view_manager.h" |  | ||||||
| #include "ibutton_event.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| 
 |  | ||||||
| iButtonAppViewManager::iButtonAppViewManager() { |  | ||||||
|     event_queue = osMessageQueueNew(10, sizeof(iButtonEvent), NULL); |  | ||||||
| 
 |  | ||||||
|     view_dispatcher = view_dispatcher_alloc(); |  | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonAppViewManager::previous_view_callback); |  | ||||||
| 
 |  | ||||||
|     dialog_ex = dialog_ex_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewDialogEx), |  | ||||||
|         dialog_ex_get_view(dialog_ex)); |  | ||||||
| 
 |  | ||||||
|     submenu = submenu_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewSubmenu), |  | ||||||
|         submenu_get_view(submenu)); |  | ||||||
| 
 |  | ||||||
|     text_input = text_input_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewTextInput), |  | ||||||
|         text_input_get_view(text_input)); |  | ||||||
| 
 |  | ||||||
|     byte_input = byte_input_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewByteInput), |  | ||||||
|         byte_input_get_view(byte_input)); |  | ||||||
| 
 |  | ||||||
|     popup = popup_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewPopup), |  | ||||||
|         popup_get_view(popup)); |  | ||||||
| 
 |  | ||||||
|     widget = widget_alloc(); |  | ||||||
|     view_dispatcher_add_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewWidget), |  | ||||||
|         widget_get_view(widget)); |  | ||||||
| 
 |  | ||||||
|     gui = static_cast<Gui*>(furi_record_open("gui")); |  | ||||||
|     view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); |  | ||||||
| 
 |  | ||||||
|     //TODO think about that method, seems unsafe and over-engineered
 |  | ||||||
|     view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback); |  | ||||||
|     view_set_previous_callback(submenu_get_view(submenu), callback); |  | ||||||
|     view_set_previous_callback(text_input_get_view(text_input), callback); |  | ||||||
|     view_set_previous_callback(byte_input_get_view(byte_input), callback); |  | ||||||
|     view_set_previous_callback(popup_get_view(popup), callback); |  | ||||||
|     view_set_previous_callback(widget_get_view(widget), callback); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonAppViewManager::~iButtonAppViewManager() { |  | ||||||
|     // remove views
 |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewDialogEx)); |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewSubmenu)); |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewTextInput)); |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewPopup)); |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, |  | ||||||
|         static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewByteInput)); |  | ||||||
|     view_dispatcher_remove_view( |  | ||||||
|         view_dispatcher, static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewWidget)); |  | ||||||
| 
 |  | ||||||
|     // free view modules
 |  | ||||||
|     popup_free(popup); |  | ||||||
|     text_input_free(text_input); |  | ||||||
|     byte_input_free(byte_input); |  | ||||||
|     submenu_free(submenu); |  | ||||||
|     dialog_ex_free(dialog_ex); |  | ||||||
|     widget_free(widget); |  | ||||||
| 
 |  | ||||||
|     // free dispatcher
 |  | ||||||
|     view_dispatcher_free(view_dispatcher); |  | ||||||
| 
 |  | ||||||
|     // free event queue
 |  | ||||||
|     osMessageQueueDelete(event_queue); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonAppViewManager::switch_to(Type type) { |  | ||||||
|     view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Submenu* iButtonAppViewManager::get_submenu() { |  | ||||||
|     return submenu; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Popup* iButtonAppViewManager::get_popup() { |  | ||||||
|     return popup; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| DialogEx* iButtonAppViewManager::get_dialog_ex() { |  | ||||||
|     return dialog_ex; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TextInput* iButtonAppViewManager::get_text_input() { |  | ||||||
|     return text_input; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ByteInput* iButtonAppViewManager::get_byte_input() { |  | ||||||
|     return byte_input; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Widget* iButtonAppViewManager::get_widget() { |  | ||||||
|     return widget; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonAppViewManager::receive_event(iButtonEvent* event) { |  | ||||||
|     if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { |  | ||||||
|         event->type = iButtonEvent::Type::EventTypeTick; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonAppViewManager::send_event(iButtonEvent* event) { |  | ||||||
|     osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0); |  | ||||||
|     furi_check(result == osOK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint32_t iButtonAppViewManager::previous_view_callback(void* context) { |  | ||||||
|     if(event_queue != NULL) { |  | ||||||
|         iButtonEvent event; |  | ||||||
|         event.type = iButtonEvent::Type::EventTypeBack; |  | ||||||
|         send_event(&event); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return VIEW_IGNORE; |  | ||||||
| } |  | ||||||
| @ -1,51 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <furi.h> |  | ||||||
| #include <gui/view_dispatcher.h> |  | ||||||
| #include <gui/modules/dialog_ex.h> |  | ||||||
| #include <gui/modules/submenu.h> |  | ||||||
| #include <gui/modules/text_input.h> |  | ||||||
| #include <gui/modules/byte_input.h> |  | ||||||
| #include <gui/modules/popup.h> |  | ||||||
| #include <gui/modules/widget.h> |  | ||||||
| #include "ibutton_event.h" |  | ||||||
| 
 |  | ||||||
| class iButtonAppViewManager { |  | ||||||
| public: |  | ||||||
|     enum class Type : uint8_t { |  | ||||||
|         iButtonAppViewTextInput, |  | ||||||
|         iButtonAppViewByteInput, |  | ||||||
|         iButtonAppViewSubmenu, |  | ||||||
|         iButtonAppViewDialogEx, |  | ||||||
|         iButtonAppViewPopup, |  | ||||||
|         iButtonAppViewWidget, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     osMessageQueueId_t event_queue; |  | ||||||
| 
 |  | ||||||
|     iButtonAppViewManager(); |  | ||||||
|     ~iButtonAppViewManager(); |  | ||||||
| 
 |  | ||||||
|     void switch_to(Type type); |  | ||||||
| 
 |  | ||||||
|     Submenu* get_submenu(); |  | ||||||
|     Popup* get_popup(); |  | ||||||
|     DialogEx* get_dialog_ex(); |  | ||||||
|     TextInput* get_text_input(); |  | ||||||
|     ByteInput* get_byte_input(); |  | ||||||
|     Widget* get_widget(); |  | ||||||
| 
 |  | ||||||
|     void receive_event(iButtonEvent* event); |  | ||||||
|     void send_event(iButtonEvent* event); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     ViewDispatcher* view_dispatcher; |  | ||||||
|     DialogEx* dialog_ex; |  | ||||||
|     Submenu* submenu; |  | ||||||
|     TextInput* text_input; |  | ||||||
|     ByteInput* byte_input; |  | ||||||
|     Popup* popup; |  | ||||||
|     Widget* widget; |  | ||||||
|     Gui* gui; |  | ||||||
| 
 |  | ||||||
|     uint32_t previous_view_callback(void* context); |  | ||||||
| }; |  | ||||||
| @ -1,66 +0,0 @@ | |||||||
| #include "ibutton_scene_add_type.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| 
 |  | ||||||
| typedef enum { |  | ||||||
|     SubmenuIndexCyfral, |  | ||||||
|     SubmenuIndexDallas, |  | ||||||
|     SubmenuIndexMetakom, |  | ||||||
| } SubmenuIndex; |  | ||||||
| 
 |  | ||||||
| static void submenu_callback(void* context, uint32_t index) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneAddType::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |  | ||||||
| 
 |  | ||||||
|     submenu_add_item(submenu, "Cyfral", SubmenuIndexCyfral, submenu_callback, app); |  | ||||||
|     submenu_add_item(submenu, "Dallas", SubmenuIndexDallas, submenu_callback, app); |  | ||||||
|     submenu_add_item(submenu, "Metakom", SubmenuIndexMetakom, submenu_callback, app); |  | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneAddType::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { |  | ||||||
|         submenu_item_selected = event->payload.menu_index; |  | ||||||
|         iButtonKey* key = app->get_key(); |  | ||||||
| 
 |  | ||||||
|         switch(event->payload.menu_index) { |  | ||||||
|         case SubmenuIndexCyfral: |  | ||||||
|             ibutton_key_set_type(key, iButtonKeyCyfral); |  | ||||||
|             break; |  | ||||||
|         case SubmenuIndexDallas: |  | ||||||
|             ibutton_key_set_type(key, iButtonKeyDS1990); |  | ||||||
|             break; |  | ||||||
|         case SubmenuIndexMetakom: |  | ||||||
|             ibutton_key_set_type(key, iButtonKeyMetakom); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         ibutton_key_set_name(key, ""); |  | ||||||
|         ibutton_key_clear_data(key); |  | ||||||
|         app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue); |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneAddType::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view = app->get_view_manager(); |  | ||||||
|     Submenu* submenu = view->get_submenu(); |  | ||||||
| 
 |  | ||||||
|     submenu_reset(submenu); |  | ||||||
| } |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneAddType : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     uint32_t submenu_item_selected = 0; |  | ||||||
| }; |  | ||||||
| @ -1,53 +0,0 @@ | |||||||
| #include "ibutton_scene_add_value.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| #include <dolphin/dolphin.h> |  | ||||||
| 
 |  | ||||||
| static void byte_input_callback(void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeByteEditResult; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneAddValue::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     ByteInput* byte_input = view_manager->get_byte_input(); |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
| 
 |  | ||||||
|     memcpy(this->new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)); |  | ||||||
| 
 |  | ||||||
|     byte_input_set_result_callback( |  | ||||||
|         byte_input, |  | ||||||
|         byte_input_callback, |  | ||||||
|         NULL, |  | ||||||
|         app, |  | ||||||
|         this->new_key_data, |  | ||||||
|         ibutton_key_get_data_size(key)); |  | ||||||
| 
 |  | ||||||
|     byte_input_set_header_text(byte_input, "Enter the key"); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneAddValue::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeByteEditResult) { |  | ||||||
|         ibutton_key_set_data(app->get_key(), this->new_key_data, IBUTTON_KEY_DATA_SIZE); |  | ||||||
|         DOLPHIN_DEED(DolphinDeedIbuttonAdd); |  | ||||||
|         app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneAddValue::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     ByteInput* byte_input = view_manager->get_byte_input(); |  | ||||||
| 
 |  | ||||||
|     byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0); |  | ||||||
|     byte_input_set_header_text(byte_input, {0}); |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| #include <one_wire/ibutton/ibutton_key.h> |  | ||||||
| 
 |  | ||||||
| class iButtonSceneAddValue : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {}; |  | ||||||
| }; |  | ||||||
| @ -1,86 +0,0 @@ | |||||||
| #include "ibutton_scene_delete_confirm.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| static void widget_callback(GuiButtonType result, InputType type, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     if(type == InputTypeShort) { |  | ||||||
|         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; |  | ||||||
|         event.payload.widget_button_result = result; |  | ||||||
|         app->get_view_manager()->send_event(&event); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
|     const uint8_t* key_data = ibutton_key_get_data_p(key); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store("\e#Delete %s?\e#", ibutton_key_get_name_p(key)); |  | ||||||
|     widget_add_text_box_element( |  | ||||||
|         widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store(), false); |  | ||||||
|     widget_add_button_element(widget, GuiButtonTypeLeft, "Cancel", widget_callback, app); |  | ||||||
|     widget_add_button_element(widget, GuiButtonTypeRight, "Delete", widget_callback, app); |  | ||||||
| 
 |  | ||||||
|     switch(ibutton_key_get_type(key)) { |  | ||||||
|     case iButtonKeyDS1990: |  | ||||||
|         app->set_text_store( |  | ||||||
|             "%02X %02X %02X %02X %02X %02X %02X %02X", |  | ||||||
|             key_data[0], |  | ||||||
|             key_data[1], |  | ||||||
|             key_data[2], |  | ||||||
|             key_data[3], |  | ||||||
|             key_data[4], |  | ||||||
|             key_data[5], |  | ||||||
|             key_data[6], |  | ||||||
|             key_data[7]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyCyfral: |  | ||||||
|         app->set_text_store("%02X %02X", key_data[0], key_data[1]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyMetakom: |  | ||||||
|         app->set_text_store( |  | ||||||
|             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom"); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     widget_add_string_element( |  | ||||||
|         widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, app->get_text_store()); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneDeleteConfirm::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) { |  | ||||||
|         if(event->payload.widget_button_result == GuiButtonTypeRight) { |  | ||||||
|             if(app->delete_key()) { |  | ||||||
|                 app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             app->switch_to_previous_scene(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteConfirm::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store(""); |  | ||||||
| 
 |  | ||||||
|     widget_reset(widget); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneDeleteConfirm : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,47 +0,0 @@ | |||||||
| #include "ibutton_scene_delete_success.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| static void popup_callback(void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeBack; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Popup* popup = view_manager->get_popup(); |  | ||||||
| 
 |  | ||||||
|     popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); |  | ||||||
|     popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); |  | ||||||
| 
 |  | ||||||
|     popup_set_callback(popup, popup_callback); |  | ||||||
|     popup_set_context(popup, app); |  | ||||||
|     popup_set_timeout(popup, 1500); |  | ||||||
|     popup_enable_timeout(popup); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneDeleteSuccess::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeBack) { |  | ||||||
|         app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneSelectKey}); |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) { |  | ||||||
|     Popup* popup = app->get_view_manager()->get_popup(); |  | ||||||
| 
 |  | ||||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); |  | ||||||
|     popup_set_icon(popup, 0, 0, NULL); |  | ||||||
| 
 |  | ||||||
|     popup_disable_timeout(popup); |  | ||||||
|     popup_set_context(popup, NULL); |  | ||||||
|     popup_set_callback(popup, NULL); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneDeleteSuccess : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneEmulate : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,51 +0,0 @@ | |||||||
| #include "ibutton_scene_exit_confirm.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| static void widget_callback(GuiButtonType result, InputType type, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     if(type == InputTypeShort) { |  | ||||||
|         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; |  | ||||||
|         event.payload.widget_button_result = result; |  | ||||||
|         app->get_view_manager()->send_event(&event); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneExitConfirm::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
| 
 |  | ||||||
|     widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", widget_callback, app); |  | ||||||
|     widget_add_button_element(widget, GuiButtonTypeRight, "Stay", widget_callback, app); |  | ||||||
|     widget_add_string_element( |  | ||||||
|         widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu"); |  | ||||||
|     widget_add_string_element( |  | ||||||
|         widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost"); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneExitConfirm::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) { |  | ||||||
|         if(event->payload.widget_button_result == GuiButtonTypeLeft) { |  | ||||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); |  | ||||||
|         } else if(event->payload.widget_button_result == GuiButtonTypeRight) { |  | ||||||
|             app->switch_to_previous_scene(); |  | ||||||
|         } |  | ||||||
|         consumed = true; |  | ||||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneExitConfirm::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
|     widget_reset(widget); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneExitConfirm : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| 
 |  | ||||||
| class iButtonApp; |  | ||||||
| 
 |  | ||||||
| class iButtonScene { |  | ||||||
| public: |  | ||||||
|     virtual void on_enter(iButtonApp* app) = 0; |  | ||||||
|     virtual bool on_event(iButtonApp* app, iButtonEvent* event) = 0; |  | ||||||
|     virtual void on_exit(iButtonApp* app) = 0; |  | ||||||
|     virtual ~iButtonScene(){}; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| }; |  | ||||||
| @ -1,59 +0,0 @@ | |||||||
| #include "ibutton_scene_info.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| void iButtonSceneInfo::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
|     const uint8_t* key_data = ibutton_key_get_data_p(key); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store("%s", ibutton_key_get_name_p(key)); |  | ||||||
|     widget_add_text_box_element( |  | ||||||
|         widget, 0, 0, 128, 28, AlignCenter, AlignCenter, app->get_text_store(), false); |  | ||||||
| 
 |  | ||||||
|     switch(ibutton_key_get_type(key)) { |  | ||||||
|     case iButtonKeyDS1990: |  | ||||||
|         app->set_text_store( |  | ||||||
|             "%02X %02X %02X %02X %02X %02X %02X %02X", |  | ||||||
|             key_data[0], |  | ||||||
|             key_data[1], |  | ||||||
|             key_data[2], |  | ||||||
|             key_data[3], |  | ||||||
|             key_data[4], |  | ||||||
|             key_data[5], |  | ||||||
|             key_data[6], |  | ||||||
|             key_data[7]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas"); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyMetakom: |  | ||||||
|         app->set_text_store( |  | ||||||
|             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom"); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyCyfral: |  | ||||||
|         app->set_text_store("%02X %02X", key_data[0], key_data[1]); |  | ||||||
|         widget_add_string_element( |  | ||||||
|             widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     widget_add_string_element( |  | ||||||
|         widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, app->get_text_store()); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneInfo::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneInfo::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Widget* widget = view_manager->get_widget(); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store(""); |  | ||||||
| 
 |  | ||||||
|     widget_reset(widget); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneInfo : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| #include "ibutton_scene_read.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| #include <dolphin/dolphin.h> |  | ||||||
| 
 |  | ||||||
| static void read_callback(void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event = {.type = iButtonEvent::Type::EventTypeWorkerRead}; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneRead::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Popup* popup = view_manager->get_popup(); |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
|     iButtonWorker* worker = app->get_key_worker(); |  | ||||||
|     DOLPHIN_DEED(DolphinDeedIbuttonRead); |  | ||||||
| 
 |  | ||||||
|     popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); |  | ||||||
|     popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); |  | ||||||
|     popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); |  | ||||||
|     ibutton_key_set_name(key, ""); |  | ||||||
| 
 |  | ||||||
|     ibutton_worker_read_set_callback(worker, read_callback, app); |  | ||||||
|     ibutton_worker_read_start(worker, key); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeWorkerRead) { |  | ||||||
|         consumed = true; |  | ||||||
| 
 |  | ||||||
|         iButtonKey* key = app->get_key(); |  | ||||||
|         bool success = false; |  | ||||||
|         if(ibutton_key_get_type(key) == iButtonKeyDS1990) { |  | ||||||
|             if(!ibutton_key_dallas_crc_is_valid(key)) { |  | ||||||
|                 app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError); |  | ||||||
|             } else if(!ibutton_key_dallas_is_1990_key(key)) { |  | ||||||
|                 app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError); |  | ||||||
|             } else { |  | ||||||
|                 success = true; |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             success = true; |  | ||||||
|         } |  | ||||||
|         if(success) { |  | ||||||
|             app->notify_success(); |  | ||||||
|             app->notify_green_on(); |  | ||||||
|             DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess); |  | ||||||
|         } |  | ||||||
|     } else if(event->type == iButtonEvent::Type::EventTypeTick) { |  | ||||||
|         consumed = true; |  | ||||||
|         app->notify_read(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneRead::on_exit(iButtonApp* app) { |  | ||||||
|     Popup* popup = app->get_view_manager()->get_popup(); |  | ||||||
|     ibutton_worker_stop(app->get_key_worker()); |  | ||||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); |  | ||||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); |  | ||||||
|     popup_set_icon(popup, 0, 0, NULL); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneRead : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| #include "ibutton_scene_read_crc_error.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| #include <one_wire/maxim_crc.h> |  | ||||||
| 
 |  | ||||||
| static void dialog_ex_callback(DialogExResult result, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeDialogResult; |  | ||||||
|     event.payload.dialog_result = result; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadCRCError::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |  | ||||||
|     const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store( |  | ||||||
|         "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", |  | ||||||
|         key_data[0], |  | ||||||
|         key_data[1], |  | ||||||
|         key_data[2], |  | ||||||
|         key_data[3], |  | ||||||
|         key_data[4], |  | ||||||
|         key_data[5], |  | ||||||
|         key_data[6], |  | ||||||
|         key_data[7], |  | ||||||
|         maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); |  | ||||||
| 
 |  | ||||||
|     dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); |  | ||||||
|     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); |  | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, "Retry"); |  | ||||||
|     dialog_ex_set_right_button_text(dialog_ex, "More"); |  | ||||||
|     dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); |  | ||||||
|     dialog_ex_set_context(dialog_ex, app); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); |  | ||||||
|     app->notify_error(); |  | ||||||
|     app->notify_red_on(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneReadCRCError::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeDialogResult) { |  | ||||||
|         if(event->payload.dialog_result == DialogExResultRight) { |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu); |  | ||||||
|         } else { |  | ||||||
|             app->switch_to_previous_scene(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadCRCError::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store(""); |  | ||||||
| 
 |  | ||||||
|     dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); |  | ||||||
|     dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); |  | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, NULL); |  | ||||||
|     dialog_ex_set_result_callback(dialog_ex, NULL); |  | ||||||
|     dialog_ex_set_context(dialog_ex, NULL); |  | ||||||
| 
 |  | ||||||
|     app->notify_red_off(); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneReadCRCError : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
| @ -1,65 +0,0 @@ | |||||||
| #include "ibutton_scene_read_key_menu.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| 
 |  | ||||||
| typedef enum { |  | ||||||
|     SubmenuIndexSave, |  | ||||||
|     SubmenuIndexEmulate, |  | ||||||
|     SubmenuIndexWrite, |  | ||||||
| } SubmenuIndex; |  | ||||||
| 
 |  | ||||||
| static void submenu_callback(void* context, uint32_t index) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadKeyMenu::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |  | ||||||
| 
 |  | ||||||
|     submenu_add_item(submenu, "Save", SubmenuIndexSave, submenu_callback, app); |  | ||||||
|     submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app); |  | ||||||
|     if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) { |  | ||||||
|         submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app); |  | ||||||
|     } |  | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneReadKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { |  | ||||||
|         submenu_item_selected = event->payload.menu_index; |  | ||||||
|         switch(event->payload.menu_index) { |  | ||||||
|         case SubmenuIndexWrite: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneWrite); |  | ||||||
|             break; |  | ||||||
|         case SubmenuIndexEmulate: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneEmulate); |  | ||||||
|             break; |  | ||||||
|         case SubmenuIndexSave: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         consumed = true; |  | ||||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { |  | ||||||
|         app->switch_to_previous_scene(); |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadKeyMenu::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view = app->get_view_manager(); |  | ||||||
|     Submenu* submenu = view->get_submenu(); |  | ||||||
| 
 |  | ||||||
|     submenu_reset(submenu); |  | ||||||
| } |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneReadKeyMenu : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     uint32_t submenu_item_selected = 0; |  | ||||||
| }; |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| #include "ibutton_scene_read_not_key_error.h" |  | ||||||
| #include "../ibutton_app.h" |  | ||||||
| #include <one_wire/maxim_crc.h> |  | ||||||
| 
 |  | ||||||
| static void dialog_ex_callback(DialogExResult result, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeDialogResult; |  | ||||||
|     event.payload.dialog_result = result; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |  | ||||||
|     const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store( |  | ||||||
|         "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", |  | ||||||
|         key_data[0], |  | ||||||
|         key_data[1], |  | ||||||
|         key_data[2], |  | ||||||
|         key_data[3], |  | ||||||
|         key_data[4], |  | ||||||
|         key_data[5], |  | ||||||
|         key_data[6], |  | ||||||
|         key_data[7], |  | ||||||
|         maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); |  | ||||||
| 
 |  | ||||||
|     dialog_ex_set_header(dialog_ex, "ERROR:", 64, 10, AlignCenter, AlignCenter); |  | ||||||
|     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); |  | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, "Retry"); |  | ||||||
|     dialog_ex_set_right_button_text(dialog_ex, "More"); |  | ||||||
|     dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); |  | ||||||
|     dialog_ex_set_context(dialog_ex, app); |  | ||||||
| 
 |  | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); |  | ||||||
|     app->notify_error(); |  | ||||||
|     app->notify_red_on(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonSceneReadNotKeyError::on_event(iButtonApp* app, iButtonEvent* event) { |  | ||||||
|     bool consumed = false; |  | ||||||
| 
 |  | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeDialogResult) { |  | ||||||
|         if(event->payload.dialog_result == DialogExResultRight) { |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu); |  | ||||||
|         } else { |  | ||||||
|             app->switch_to_previous_scene(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         consumed = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return consumed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonSceneReadNotKeyError::on_exit(iButtonApp* app) { |  | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |  | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |  | ||||||
| 
 |  | ||||||
|     app->set_text_store(""); |  | ||||||
| 
 |  | ||||||
|     dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); |  | ||||||
|     dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop); |  | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, NULL); |  | ||||||
|     dialog_ex_set_result_callback(dialog_ex, NULL); |  | ||||||
|     dialog_ex_set_context(dialog_ex, NULL); |  | ||||||
| 
 |  | ||||||
|     app->notify_red_off(); |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "ibutton_scene_generic.h" |  | ||||||
| 
 |  | ||||||
| class iButtonSceneReadNotKeyError : public iButtonScene { |  | ||||||
| public: |  | ||||||
|     void on_enter(iButtonApp* app) final; |  | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |  | ||||||
|     void on_exit(iButtonApp* app) final; |  | ||||||
| }; |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov