Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
		
						commit
						e64de44b73
					
				| @ -83,4 +83,4 @@ SpacesInParentheses: false | ||||
| SpacesInSquareBrackets: false | ||||
| Standard: Cpp03 | ||||
| TabWidth: 4 | ||||
| UseTab: Never | ||||
| UseTab: Never | ||||
|  | ||||
							
								
								
									
										2
									
								
								.github/workflows/build_toolchain.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build_toolchain.yml
									
									
									
									
										vendored
									
									
								
							| @ -43,4 +43,4 @@ jobs: | ||||
|           labels: ${{ steps.meta.outputs.labels }} | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           cache-from: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache | ||||
|           cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max | ||||
|           cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max | ||||
|  | ||||
							
								
								
									
										2
									
								
								.github/workflows/check_submodules.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check_submodules.yml
									
									
									
									
										vendored
									
									
								
							| @ -14,4 +14,4 @@ jobs: | ||||
|       with: | ||||
|         path: assets/protobuf | ||||
|         branch: dev | ||||
|         fetch_depth: 50 | ||||
|         fetch_depth: 50 | ||||
|  | ||||
| @ -149,6 +149,7 @@ const AboutDialogScreen about_screens[] = { | ||||
| const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); | ||||
| 
 | ||||
| int32_t about_settings_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     DialogsApp* dialogs = furi_record_open("dialogs"); | ||||
|     DialogMessage* message = dialog_message_alloc(); | ||||
| 
 | ||||
|  | ||||
| @ -2,9 +2,10 @@ | ||||
| 
 | ||||
| // app enter function
 | ||||
| extern "C" int32_t accessor_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     AccessorApp* app = new AccessorApp(); | ||||
|     app->run(); | ||||
|     delete app; | ||||
| 
 | ||||
|     return 255; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -51,4 +51,4 @@ private: | ||||
|     OneWireHost* onewire_host; | ||||
| 
 | ||||
|     NotificationApp* notification; | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -64,7 +64,7 @@ void AccessorAppViewManager::send_event(AccessorEvent* event) { | ||||
|     furi_check(result == osOK); | ||||
| } | ||||
| 
 | ||||
| uint32_t AccessorAppViewManager::previous_view_callback(void* context) { | ||||
| uint32_t AccessorAppViewManager::previous_view_callback(void*) { | ||||
|     if(event_queue != NULL) { | ||||
|         AccessorEvent event; | ||||
|         event.type = AccessorEvent::Type::Back; | ||||
| @ -76,4 +76,4 @@ uint32_t AccessorAppViewManager::previous_view_callback(void* context) { | ||||
| 
 | ||||
| void AccessorAppViewManager::add_view(ViewType view_type, View* view) { | ||||
|     view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -36,4 +36,4 @@ private: | ||||
|     // view elements
 | ||||
|     Submenu* submenu; | ||||
|     Popup* popup; | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -27,4 +27,4 @@ private: | ||||
|     static int _wiegandType; | ||||
|     static unsigned long _code; | ||||
|     static unsigned long _codeHigh; | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -10,4 +10,4 @@ public: | ||||
|     virtual void on_exit(AccessorApp* app) = 0; | ||||
| 
 | ||||
| private: | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -6,4 +6,4 @@ public: | ||||
|     void on_enter(AccessorApp* app) final; | ||||
|     bool on_event(AccessorApp* app, AccessorEvent* event) final; | ||||
|     void on_exit(AccessorApp* app) final; | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -55,6 +55,7 @@ extern void crypto_on_system_start(); | ||||
| extern void ibutton_on_system_start(); | ||||
| extern void infrared_on_system_start(); | ||||
| extern void lfrfid_on_system_start(); | ||||
| extern void music_player_on_system_start(); | ||||
| extern void nfc_on_system_start(); | ||||
| extern void storage_on_system_start(); | ||||
| extern void subghz_on_system_start(); | ||||
| @ -280,6 +281,10 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { | ||||
|     infrared_on_system_start, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_MUSIC_PLAYER | ||||
|     music_player_on_system_start, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_NFC | ||||
|     nfc_on_system_start, | ||||
| #endif | ||||
| @ -332,7 +337,7 @@ const FlipperApplication FLIPPER_PLUGINS[] = { | ||||
| #ifdef APP_MUSIC_PLAYER | ||||
|     {.app = music_player_app, | ||||
|      .name = "Music Player", | ||||
|      .stack_size = 1024, | ||||
|      .stack_size = 2048, | ||||
|      .icon = &A_Plugins_14, | ||||
|      .flags = FlipperApplicationFlagDefault}, | ||||
| #endif | ||||
|  | ||||
| @ -66,6 +66,7 @@ void archive_free(ArchiveApp* archive) { | ||||
| } | ||||
| 
 | ||||
| int32_t archive_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     ArchiveApp* archive = archive_alloc(); | ||||
|     scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); | ||||
|     view_dispatcher_run(archive->view_dispatcher); | ||||
|  | ||||
| @ -7,8 +7,8 @@ static const char* known_apps[] = { | ||||
| }; | ||||
| 
 | ||||
| ArchiveAppTypeEnum archive_get_app_type(const char* path) { | ||||
|     for(size_t i = 0; i < SIZEOF_ARRAY(known_apps); i++) { | ||||
|         if(strncmp(path, known_apps[i], strlen(known_apps[i])) != STRING_FAILURE) { | ||||
|     for(size_t i = 0; i < COUNT_OF(known_apps); i++) { | ||||
|         if(strncmp(path, known_apps[i], strlen(known_apps[i])) == 0) { | ||||
|             return i; | ||||
|         } | ||||
|     } | ||||
| @ -16,6 +16,7 @@ ArchiveAppTypeEnum archive_get_app_type(const char* path) { | ||||
| } | ||||
| 
 | ||||
| bool archive_app_is_available(void* context, const char* path) { | ||||
|     UNUSED(context); | ||||
|     furi_assert(path); | ||||
| 
 | ||||
|     ArchiveAppTypeEnum app = archive_get_app_type(path); | ||||
|  | ||||
| @ -11,7 +11,7 @@ static const ArchiveFileTypeEnum app_file_types[] = { | ||||
|     [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]; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -6,7 +6,8 @@ | ||||
| bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { | ||||
|     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; | ||||
|     } | ||||
| 
 | ||||
| @ -20,12 +21,14 @@ void archive_update_offset(ArchiveBrowserView* browser) { | ||||
|         browser->view, (ArchiveBrowserViewModel * model) { | ||||
|             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; | ||||
|             } 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) { | ||||
|                 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; | ||||
| @ -77,9 +80,10 @@ void archive_set_item_count(ArchiveBrowserView* browser, uint32_t count) { | ||||
|     with_view_model( | ||||
|         browser->view, (ArchiveBrowserViewModel * model) { | ||||
|             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; | ||||
|         }); | ||||
|     archive_update_offset(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 + 1); | ||||
|             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; | ||||
|             return false; | ||||
|         }); | ||||
| @ -112,14 +116,14 @@ void archive_file_array_swap(ArchiveBrowserView* browser, int8_t dir) { | ||||
|         browser->view, (ArchiveBrowserViewModel * model) { | ||||
|             ArchiveFile_t temp; | ||||
|             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) { | ||||
|                 ArchiveFile_t_init(&temp); | ||||
|                 files_array_pop_at(&temp, model->files, array_size); | ||||
|                 files_array_push_at(model->files, model->item_idx, 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); | ||||
|                 files_array_pop_at(&temp, model->files, 0); | ||||
|                 files_array_push_at(model->files, array_size, temp); | ||||
| @ -156,7 +160,7 @@ bool archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { | ||||
|                 } else { | ||||
|                     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; | ||||
|         }); | ||||
| @ -195,7 +199,7 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { | ||||
| 
 | ||||
|     with_view_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; | ||||
|             return false; | ||||
|         }); | ||||
| @ -246,6 +250,7 @@ void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | ||||
|         }); | ||||
| } | ||||
| void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | ||||
|     UNUSED(tab); // FIXME?
 | ||||
|     furi_assert(browser); | ||||
| 
 | ||||
|     with_view_model( | ||||
| @ -396,8 +401,6 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     archive_dir_count_items(browser, string_get_cstr(name)); | ||||
| 
 | ||||
|     if(string_cmp(browser->path, name) != 0) { | ||||
|         with_view_model( | ||||
|             browser->view, (ArchiveBrowserViewModel * model) { | ||||
| @ -410,6 +413,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { | ||||
|         string_set(browser->path, name); | ||||
|     } | ||||
| 
 | ||||
|     archive_dir_count_items(browser, string_get_cstr(name)); | ||||
|     archive_switch_dir(browser, string_get_cstr(browser->path)); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -42,7 +42,7 @@ static const ArchiveFileTypeEnum known_type[] = { | ||||
|     [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]; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -54,7 +54,7 @@ void archive_set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* | ||||
|     } else { | ||||
|         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(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { | ||||
|                 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) { | ||||
|     UNUSED(browser); | ||||
|     Loader* loader = furi_record_open("loader"); | ||||
| 
 | ||||
|     LoaderStatus status; | ||||
| @ -95,6 +96,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | ||||
|             if(known_app) { | ||||
|                 archive_run_in_app(browser, selected); | ||||
|             } | ||||
|             archive_show_file_menu(browser, false); | ||||
|             consumed = true; | ||||
|             break; | ||||
|         case ArchiveBrowserEventFileMenuPin: | ||||
|  | ||||
| @ -106,17 +106,17 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { | ||||
|     size_t array_size = files_array_size(model->files); | ||||
|     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; | ||||
|         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; | ||||
| 
 | ||||
|         ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading; | ||||
| 
 | ||||
|         if(archive_is_item_in_array(model, idx)) { | ||||
|             ArchiveFile_t* file = | ||||
|                 files_array_get(model->files, CLAMP(idx - model->array_offset, array_size - 1, 0)); | ||||
|             ArchiveFile_t* file = files_array_get( | ||||
|                 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); | ||||
|             archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); | ||||
|             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_set_color(canvas, ColorBlack); | ||||
|     canvas_draw_frame(canvas, 1, 0, 50, 12); | ||||
|     canvas_draw_line(canvas, 0, 1, 0, 11); | ||||
|     canvas_draw_line(canvas, 1, 12, 49, 12); | ||||
|     canvas_draw_str_aligned(canvas, 26, 9, AlignCenter, AlignBottom, tab_name); | ||||
|     canvas_draw_rframe(canvas, 0, 0, 51, 13, 1); // frame
 | ||||
|     canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right
 | ||||
|     canvas_draw_line(canvas, 1, 11, 49, 11); // shadow bottom
 | ||||
|     canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); | ||||
| 
 | ||||
|     canvas_draw_frame(canvas, 108, 0, 20, 12); | ||||
|     canvas_draw_line(canvas, 107, 1, 107, 11); | ||||
|     canvas_draw_line(canvas, 108, 12, 126, 12); | ||||
|     canvas_draw_rframe(canvas, 107, 0, 21, 13, 1); | ||||
|     canvas_draw_line(canvas, 126, 1, 126, 11); | ||||
|     canvas_draw_line(canvas, 108, 11, 126, 11); | ||||
| 
 | ||||
|     if(model->move_fav) { | ||||
|         canvas_draw_icon(canvas, 111, 4, &I_ButtonUp_7x4); | ||||
|         canvas_draw_icon(canvas, 118, 4, &I_ButtonDown_7x4); | ||||
|         canvas_draw_icon(canvas, 110, 4, &I_ButtonUp_7x4); | ||||
|         canvas_draw_icon(canvas, 117, 4, &I_ButtonDown_7x4); | ||||
|     } else { | ||||
|         canvas_draw_icon(canvas, 112, 2, &I_ButtonLeft_4x7); | ||||
|         canvas_draw_icon(canvas, 120, 2, &I_ButtonRight_4x7); | ||||
|         canvas_draw_icon(canvas, 111, 2, &I_ButtonLeft_4x7); | ||||
|         canvas_draw_icon(canvas, 119, 2, &I_ButtonRight_4x7); | ||||
|     } | ||||
| 
 | ||||
|     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) && | ||||
|        (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; | ||||
|     } | ||||
| 
 | ||||
| @ -347,7 +347,7 @@ ArchiveBrowserView* browser_alloc() { | ||||
|     browser->view = view_alloc(); | ||||
|     view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel)); | ||||
|     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); | ||||
| 
 | ||||
|     string_init(browser->path); | ||||
| @ -376,4 +376,4 @@ void browser_free(ArchiveBrowserView* browser) { | ||||
| 
 | ||||
|     view_free(browser->view); | ||||
|     free(browser); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -13,8 +13,8 @@ | ||||
| #define MAX_NAME_LEN 255 | ||||
| #define MAX_EXT_LEN 6 | ||||
| #define FRAME_HEIGHT 12 | ||||
| #define MENU_ITEMS 4 | ||||
| #define MOVE_OFFSET 5 | ||||
| #define MENU_ITEMS 4u | ||||
| #define MOVE_OFFSET 5u | ||||
| 
 | ||||
| typedef enum { | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(event); | ||||
|     // BadUsbApp* bad_usb = context;
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void bad_usb_scene_file_select_on_exit(void* context) { | ||||
|     UNUSED(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); | ||||
|     with_view_model( | ||||
|         bad_usb->view, (BadUsbModel * model) { | ||||
|             UNUSED(model); | ||||
|             bad_usb->callback = callback; | ||||
|             bad_usb->context = context; | ||||
|             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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
|     string_t buffer; | ||||
|     string_init(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) { | ||||
|     UNUSED(context); | ||||
|     int channel = 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) { | ||||
|     UNUSED(context); | ||||
|     int channel = 0; | ||||
| 
 | ||||
|     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)) { | ||||
|             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); | ||||
|         } | ||||
| 
 | ||||
| @ -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) { | ||||
|     UNUSED(context); | ||||
|     int channel = 0; | ||||
|     int pattern = 0; | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     int channel = 0; | ||||
|     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"); | ||||
|         furi_hal_bt_start_packet_rx(channel, datarate); | ||||
| 
 | ||||
|         float rssi_raw = 0; | ||||
|         while(!cli_cmd_interrupt_received(cli)) { | ||||
|             osDelay(250); | ||||
|             rssi_raw = furi_hal_bt_get_rssi(); | ||||
|             printf("RSSI: %03.1f dB\r", rssi_raw); | ||||
|             printf("RSSI: %03.1f dB\r", (double)furi_hal_bt_get_rssi()); | ||||
|             fflush(stdout); | ||||
|         } | ||||
|         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) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(args); | ||||
|     osMessageQueueId_t queue = osMessageQueueNew(20, sizeof(GapAddress), NULL); | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     furi_record_open("bt"); | ||||
| 
 | ||||
|     string_t cmd; | ||||
|  | ||||
| @ -19,10 +19,12 @@ void bt_debug_submenu_callback(void* context, uint32_t index) { | ||||
| } | ||||
| 
 | ||||
| uint32_t bt_debug_exit(void* context) { | ||||
|     UNUSED(context); | ||||
|     return VIEW_NONE; | ||||
| } | ||||
| 
 | ||||
| uint32_t bt_debug_start_view(void* context) { | ||||
|     UNUSED(context); | ||||
|     return BtDebugAppViewSubmenu; | ||||
| } | ||||
| 
 | ||||
| @ -94,6 +96,7 @@ void bt_debug_app_free(BtDebugApp* app) { | ||||
| } | ||||
| 
 | ||||
| int32_t bt_debug_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     if(furi_hal_bt_get_radio_stack() != FuriHalBtStackHciLayer) { | ||||
|         FURI_LOG_E(TAG, "Incorrect radio stack, replace with HciLayer for tests."); | ||||
|         DialogsApp* dialogs = furi_record_open("dialogs"); | ||||
|  | ||||
| @ -141,7 +141,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_carrier_test->bt_test, | ||||
|         "Mode", | ||||
|         SIZEOF_ARRAY(bt_param_mode), | ||||
|         COUNT_OF(bt_param_mode), | ||||
|         bt_carrier_test_mode_changed, | ||||
|         bt_carrier_test); | ||||
|     bt_test_set_current_value_index(param, 0); | ||||
| @ -151,7 +151,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_carrier_test->bt_test, | ||||
|         "Channel", | ||||
|         SIZEOF_ARRAY(bt_param_channel), | ||||
|         COUNT_OF(bt_param_channel), | ||||
|         bt_carrier_test_channel_changed, | ||||
|         bt_carrier_test); | ||||
|     bt_test_set_current_value_index(param, 0); | ||||
| @ -162,7 +162,7 @@ BtCarrierTest* bt_carrier_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_carrier_test->bt_test, | ||||
|         "Power", | ||||
|         SIZEOF_ARRAY(bt_param_power), | ||||
|         COUNT_OF(bt_param_power), | ||||
|         bt_carrier_test_param_channel, | ||||
|         bt_carrier_test); | ||||
|     bt_test_set_current_value_index(param, 0); | ||||
|  | ||||
| @ -109,7 +109,7 @@ BtPacketTest* bt_packet_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_packet_test->bt_test, | ||||
|         "Mode", | ||||
|         SIZEOF_ARRAY(bt_param_mode), | ||||
|         COUNT_OF(bt_param_mode), | ||||
|         bt_packet_test_mode_changed, | ||||
|         bt_packet_test); | ||||
|     bt_test_set_current_value_index(param, 0); | ||||
| @ -119,7 +119,7 @@ BtPacketTest* bt_packet_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_packet_test->bt_test, | ||||
|         "Channel", | ||||
|         SIZEOF_ARRAY(bt_param_channel), | ||||
|         COUNT_OF(bt_param_channel), | ||||
|         bt_packet_test_channel_changed, | ||||
|         bt_packet_test); | ||||
|     bt_test_set_current_value_index(param, 0); | ||||
| @ -129,7 +129,7 @@ BtPacketTest* bt_packet_test_alloc() { | ||||
|     param = bt_test_param_add( | ||||
|         bt_packet_test->bt_test, | ||||
|         "Data rate", | ||||
|         SIZEOF_ARRAY(bt_param_data_rate), | ||||
|         COUNT_OF(bt_param_data_rate), | ||||
|         bt_packet_test_param_channel, | ||||
|         bt_packet_test); | ||||
|     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); | ||||
|     if(model->state == BtTestStateStarted) { | ||||
|         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); | ||||
|         } | ||||
|     } 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) { | ||||
|     UNUSED(context); | ||||
|     return BtHidViewExitConfirm; | ||||
| } | ||||
| 
 | ||||
| uint32_t bt_hid_exit(void* context) { | ||||
|     UNUSED(context); | ||||
|     return VIEW_NONE; | ||||
| } | ||||
| 
 | ||||
| @ -139,6 +141,7 @@ void bt_hid_app_free(BtHid* app) { | ||||
| } | ||||
| 
 | ||||
| int32_t bt_hid_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     // Switch profile to Hid
 | ||||
|     BtHid* app = bt_hid_app_alloc(); | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     BtSettingsApp* app = bt_settings_app_alloc(); | ||||
|     view_dispatcher_run(app->view_dispatcher); | ||||
|     bt_settings_save(&app->settings); | ||||
|  | ||||
| @ -130,10 +130,12 @@ void cli_motd() { | ||||
| } | ||||
| 
 | ||||
| void cli_nl(Cli* cli) { | ||||
|     UNUSED(cli); | ||||
|     printf("\r\n"); | ||||
| } | ||||
| 
 | ||||
| void cli_prompt(Cli* cli) { | ||||
|     UNUSED(cli); | ||||
|     printf("\r\n>: %s", string_get_cstr(cli->line)); | ||||
|     fflush(stdout); | ||||
| } | ||||
| @ -451,6 +453,7 @@ void cli_session_close(Cli* cli) { | ||||
| } | ||||
| 
 | ||||
| int32_t cli_srv(void* p) { | ||||
|     UNUSED(p); | ||||
|     Cli* cli = cli_alloc(); | ||||
| 
 | ||||
|     // Init basic cli commands
 | ||||
|  | ||||
| @ -12,6 +12,8 @@ | ||||
| #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) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(last); | ||||
|     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 | ||||
|  */ | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| void cli_command_help(Cli* cli, string_t args, void* context) { | ||||
|     (void)args; | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
|     printf("Commands we have:"); | ||||
| 
 | ||||
|     // 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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(context); | ||||
| 
 | ||||
|     FuriHalRtcDateTime datetime = {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) { | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
|     StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1); | ||||
|     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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(context); | ||||
|     if(!string_cmp(args, "0")) { | ||||
|         NotificationApp* notification = furi_record_open("notification"); | ||||
|         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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(context); | ||||
|     if(!string_cmp(args, "0")) { | ||||
|         furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); | ||||
|         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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(context); | ||||
|     // Get first word as light name
 | ||||
|     NotificationMessage notification_led_message; | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     char pin_names[][4] = { | ||||
|         "PC0", | ||||
|         "PC1", | ||||
| @ -313,6 +330,8 @@ void cli_command_gpio_set(Cli* cli, string_t args, void* context) { | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| #else | ||||
|         UNUSED(cli); | ||||
| #endif | ||||
| 
 | ||||
|         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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
| 
 | ||||
|     const uint8_t threads_num_max = 32; | ||||
|     osThreadId_t 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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
| 
 | ||||
|     printf("Free heap size: %d\r\n", memmgr_get_free_heap()); | ||||
|     printf("Total heap size: %d\r\n", memmgr_get_total_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) { | ||||
|     UNUSED(cli); | ||||
|     UNUSED(args); | ||||
|     UNUSED(context); | ||||
| 
 | ||||
|     memmgr_heap_printf_free_blocks(); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     printf("Scanning external i2c on PC0(SCL)/PC1(SDA)\r\n" | ||||
|            "Clock: 100khz, 7bit address\r\n" | ||||
| @ -391,4 +426,4 @@ void cli_commands_init(Cli* cli) { | ||||
|     cli_add_command(cli, "led", CliCommandFlagDefault, cli_command_led, NULL); | ||||
|     cli_add_command(cli, "gpio_set", CliCommandFlagDefault, cli_command_gpio_set, NULL); | ||||
|     cli_add_command(cli, "i2c", CliCommandFlagDefault, cli_command_i2c, NULL); | ||||
| } | ||||
| } | ||||
| @ -2,4 +2,4 @@ | ||||
| 
 | ||||
| #include "cli_i.h" | ||||
| 
 | ||||
| void cli_commands_init(Cli* cli); | ||||
| void cli_commands_init(Cli* cli); | ||||
|  | ||||
| @ -86,6 +86,7 @@ static void cli_vcp_deinit() { | ||||
| } | ||||
| 
 | ||||
| static int32_t vcp_worker(void* context) { | ||||
|     UNUSED(context); | ||||
|     bool tx_idle = true; | ||||
|     size_t missed_rx = 0; | ||||
|     uint8_t last_tx_pkt_len = 0; | ||||
| @ -148,7 +149,7 @@ static int32_t vcp_worker(void* context) { | ||||
|                 if(len > 0) { | ||||
|                     furi_check( | ||||
|                         xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, osWaitForever) == | ||||
|                         len); | ||||
|                         (size_t)len); | ||||
|                 } | ||||
|             } else { | ||||
| #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) { | ||||
|     UNUSED(_cookie); | ||||
|     cli_vcp_tx((const uint8_t*)data, size); | ||||
| } | ||||
| 
 | ||||
| static void vcp_state_callback(void* context, uint8_t state) { | ||||
|     UNUSED(context); | ||||
|     if(state == 0) { | ||||
|         osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void vcp_on_cdc_control_line(void* context, uint8_t state) { | ||||
|     UNUSED(context); | ||||
|     // bit 0: DTR state, bit 1: RTS state
 | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); | ||||
|     furi_check((ret & osFlagsError) == 0); | ||||
| } | ||||
| 
 | ||||
| static void vcp_on_cdc_tx_complete(void* context) { | ||||
|     UNUSED(context); | ||||
|     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) { | ||||
|     UNUSED(cli); | ||||
|     int key_slot = 0; | ||||
|     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) { | ||||
|     UNUSED(cli); | ||||
|     int key_slot = 0; | ||||
|     int key_size = 0; | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     string_t 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) { | ||||
|     UNUSED(ctx); | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(BlinkEvent), NULL); | ||||
| 
 | ||||
|     // 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) { | ||||
|     UNUSED(context); | ||||
|     return DisplayTestViewSubmenu; | ||||
| } | ||||
| 
 | ||||
| static uint32_t display_test_exit_callback(void* context) { | ||||
|     UNUSED(context); | ||||
|     return VIEW_NONE; | ||||
| } | ||||
| 
 | ||||
| @ -210,6 +212,7 @@ void display_test_free(DisplayTest* instance) { | ||||
| } | ||||
| 
 | ||||
| int32_t display_test_run(DisplayTest* instance) { | ||||
|     UNUSED(instance); | ||||
|     view_dispatcher_switch_to_view(instance->view_dispatcher, DisplayTestViewSubmenu); | ||||
|     view_dispatcher_run(instance->view_dispatcher); | ||||
| 
 | ||||
| @ -217,6 +220,8 @@ int32_t display_test_run(DisplayTest* instance) { | ||||
| } | ||||
| 
 | ||||
| int32_t display_test_app(void* p) { | ||||
|     UNUSED(p); | ||||
| 
 | ||||
|     DisplayTest* instance = display_test_alloc(); | ||||
| 
 | ||||
|     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) { | ||||
|     UNUSED(_model); | ||||
|     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, 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) { | ||||
|     UNUSED(p); | ||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); | ||||
|     furi_check(event_queue); | ||||
| 
 | ||||
| @ -90,7 +91,7 @@ int32_t text_box_test_app(void* p) { | ||||
|     Gui* gui = furi_record_open("gui"); | ||||
|     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; | ||||
|     while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { | ||||
|         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) { | ||||
|     bool consumed = false; | ||||
|     return consumed; | ||||
|     UNUSED(event); | ||||
|     UNUSED(context); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static uint32_t uart_echo_exit(void* context) { | ||||
|     UNUSED(context); | ||||
|     return VIEW_NONE; | ||||
| } | ||||
| 
 | ||||
| @ -170,7 +172,10 @@ static int32_t uart_echo_worker(void* context) { | ||||
| 
 | ||||
|             notification_message(app->notification, &sequence_notification); | ||||
|             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) { | ||||
|     UNUSED(p); | ||||
|     UartEchoApp* app = uart_echo_app_alloc(); | ||||
|     view_dispatcher_run(app->view_dispatcher); | ||||
|     uart_echo_app_free(app); | ||||
|  | ||||
| @ -18,6 +18,7 @@ typedef struct { | ||||
| } UsbMouseEvent; | ||||
| 
 | ||||
| static void usb_mouse_render_callback(Canvas* canvas, void* ctx) { | ||||
|     UNUSED(ctx); | ||||
|     canvas_clear(canvas); | ||||
| 
 | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(UsbMouseEvent), NULL); | ||||
|     furi_check(event_queue); | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     return VIEW_NONE; | ||||
| } | ||||
| 
 | ||||
| @ -113,6 +114,7 @@ void usb_test_app_free(UsbTestApp* app) { | ||||
| } | ||||
| 
 | ||||
| int32_t usb_test_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     UsbTestApp* app = usb_test_app_alloc(); | ||||
| 
 | ||||
|     view_dispatcher_run(app->view_dispatcher); | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
| #include <notification/notification_messages.h> | ||||
| 
 | ||||
| void vibro_test_draw_callback(Canvas* canvas, void* ctx) { | ||||
|     UNUSED(ctx); | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); | ||||
| 
 | ||||
|     // Configure view port
 | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #include <gui/view_stack.h> | ||||
| #include <stdint.h> | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <m-string.h> | ||||
| #include <portmacro.h> | ||||
| #include <dolphin/dolphin.h> | ||||
| @ -364,6 +365,7 @@ static bool animation_manager_is_valid_idle_animation( | ||||
| 
 | ||||
| static StorageAnimation* | ||||
|     animation_manager_select_idle_animation(AnimationManager* animation_manager) { | ||||
|     UNUSED(animation_manager); | ||||
|     StorageAnimationList_t animation_list; | ||||
|     StorageAnimationList_init(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; | ||||
| 
 | ||||
|     StorageAnimation* selected = NULL; | ||||
|  | ||||
| @ -130,7 +130,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis | ||||
|     flipper_format_free(file); | ||||
| 
 | ||||
|     // 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]); | ||||
|     } | ||||
| 
 | ||||
| @ -142,7 +142,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { | ||||
|     furi_assert(strlen(name)); | ||||
|     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)) { | ||||
|             storage_animation = (StorageAnimation*)&dolphin_blocking[i]; | ||||
|             break; | ||||
| @ -150,7 +150,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) { | ||||
|     } | ||||
| 
 | ||||
|     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)) { | ||||
|                 storage_animation = (StorageAnimation*)&dolphin_internal[i]; | ||||
|                 break; | ||||
| @ -365,7 +365,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo | ||||
|         animation->frame_bubble_sequences = | ||||
|             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) { | ||||
|             FURI_CONST_ASSIGN_PTR( | ||||
|                 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]; | ||||
|         int8_t index = -1; | ||||
|         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 == index) { | ||||
|  | ||||
| @ -100,7 +100,8 @@ static const FrameBubble* | ||||
|         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; | ||||
| 
 | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     furi_assert(canvas); | ||||
|     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) { | ||||
|     UNUSED(p); | ||||
|     Desktop* desktop = desktop_alloc(); | ||||
| 
 | ||||
|     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) { | ||||
|     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) { | ||||
|     UNUSED(pin_code); | ||||
|     furi_assert(context); | ||||
|     DesktopSettingsApp* app = context; | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
| } | ||||
|  | ||||
| @ -47,5 +47,6 @@ bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) { | ||||
| } | ||||
| 
 | ||||
| void desktop_scene_fault_on_exit(void* context) { | ||||
|     UNUSED(context); | ||||
|     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) { | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
| } | ||||
|  | ||||
| @ -109,4 +109,5 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     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) { | ||||
|     UNUSED(event); | ||||
|     UNUSED(context); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,7 @@ static DialogsApp* dialogs_app_alloc() { | ||||
| } | ||||
| 
 | ||||
| static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) { | ||||
|     UNUSED(app); | ||||
|     switch(message->command) { | ||||
|     case DialogsAppCommandFileOpen: | ||||
|         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) { | ||||
|     UNUSED(p); | ||||
|     DialogsApp* app = dialogs_app_alloc(); | ||||
|     furi_record_create("dialogs", app); | ||||
| 
 | ||||
|  | ||||
| @ -132,4 +132,4 @@ void dialog_message_show_storage_error(DialogsApp* context, const char* error_te | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -70,4 +70,4 @@ void dialog_message_show_storage_error(DialogsApp* context, const char* error_te | ||||
|     dialog_message_set_buttons(message, "Back", NULL, NULL); | ||||
|     dialog_message_show(context, message); | ||||
|     dialog_message_free(message); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -12,4 +12,4 @@ struct DialogsApp { | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -43,4 +43,4 @@ typedef struct { | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -9,4 +9,4 @@ bool dialogs_app_process_module_file_select(const DialogsAppMessageDataFileSelec | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -9,4 +9,4 @@ DialogMessageButton dialogs_app_process_module_message(const DialogsAppMessageDa | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -95,4 +95,4 @@ void view_holder_update(View* view, void* context); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -118,6 +118,7 @@ void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event) { | ||||
| } | ||||
| 
 | ||||
| void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) { | ||||
|     UNUSED(dolphin); | ||||
|     if(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) { | ||||
|     UNUSED(p); | ||||
|     Dolphin* dolphin = dolphin_alloc(); | ||||
|     furi_record_create("dolphin", dolphin); | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,7 @@ typedef struct { | ||||
| 
 | ||||
|     uint32_t flags; | ||||
|     uint32_t icounter; | ||||
|     uint32_t butthurt; | ||||
|     int32_t butthurt; | ||||
|     uint64_t timestamp; | ||||
| } DolphinStoreData; | ||||
| 
 | ||||
|  | ||||
| @ -90,6 +90,7 @@ static void render_callback(Canvas* canvas, void* ctx) { | ||||
| } | ||||
| 
 | ||||
| int32_t passport_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     osSemaphoreId_t semaphore = osSemaphoreNew(1, 0, NULL); | ||||
|     furi_assert(semaphore); | ||||
| 
 | ||||
|  | ||||
| @ -95,6 +95,7 @@ void gpio_app_free(GpioApp* app) { | ||||
| } | ||||
| 
 | ||||
| int32_t gpio_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     GpioApp* gpio_app = gpio_app_alloc(); | ||||
| 
 | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(event); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void gpio_scene_test_on_exit(void* context) { | ||||
|     UNUSED(context); | ||||
|     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) { | ||||
|     //GpioApp* app = context;
 | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|     } | ||||
|     return consumed; | ||||
|     UNUSED(context); | ||||
|     UNUSED(event); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     UNUSED(usb_uart); | ||||
|     furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); | ||||
|     FURI_LOG_I("", "Deinit %d", vcp_ch); | ||||
|     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) { | ||||
|     UNUSED(usb_uart); | ||||
|     furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL); | ||||
|     if(uart_ch == FuriHalUartIdUSART1) | ||||
|         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) { | ||||
|     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); | ||||
| 
 | ||||
|         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_set_baudrate(usb_uart, usb_uart->cfg.baudrate); | ||||
|     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( | ||||
|             flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); | ||||
|         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); | ||||
|                 } | ||||
|                 if(usb_uart->cfg_new.flow_pins != 0) { | ||||
|                     furi_assert( | ||||
|                         (usb_uart->cfg_new.flow_pins - 1) < | ||||
|                         (sizeof(flow_pins) / sizeof(flow_pins[0]))); | ||||
|                     furi_assert((size_t)(usb_uart->cfg_new.flow_pins - 1) < COUNT_OF(flow_pins)); | ||||
|                     furi_hal_gpio_init_simple( | ||||
|                         flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); | ||||
|                     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) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(state); | ||||
| } | ||||
| 
 | ||||
| static void vcp_on_cdc_control_line(void* context, uint8_t state) { | ||||
|     UNUSED(state); | ||||
|     UsbUartBridge* usb_uart = (UsbUartBridge*)context; | ||||
|     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet); | ||||
| } | ||||
| 
 | ||||
| static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { | ||||
|     UNUSED(config); | ||||
|     UsbUartBridge* usb_uart = (UsbUartBridge*)context; | ||||
|     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); | ||||
|     with_view_model( | ||||
|         gpio_test->view, (GpioTestModel * model) { | ||||
|             UNUSED(model); | ||||
|             gpio_test->callback = callback; | ||||
|             gpio_test->context = context; | ||||
|             return false; | ||||
|  | ||||
| @ -130,6 +130,7 @@ void gpio_usb_uart_set_callback(GpioUsbUart* usb_uart, GpioUsbUartCallback callb | ||||
| 
 | ||||
|     with_view_model( | ||||
|         usb_uart->view, (GpioUsbUartModel * model) { | ||||
|             UNUSED(model); | ||||
|             usb_uart->callback = callback; | ||||
|             usb_uart->context = context; | ||||
|             return false; | ||||
|  | ||||
| @ -47,10 +47,9 @@ bool gui_redraw_fs(Gui* gui) { | ||||
| 
 | ||||
| static void gui_redraw_status_bar(Gui* gui, bool need_attention) { | ||||
|     ViewPortArray_it_t it; | ||||
|     uint8_t x; | ||||
|     uint8_t x_used = 0; | ||||
|     uint8_t left_used = 0; | ||||
|     uint8_t right_used = 0; | ||||
|     uint8_t width; | ||||
|     ViewPort* view_port; | ||||
|     canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); | ||||
|     canvas_frame_set( | ||||
|         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); | ||||
| 
 | ||||
|     // Right side
 | ||||
|     x = GUI_DISPLAY_WIDTH; | ||||
|     uint8_t x = GUI_DISPLAY_WIDTH - 1; | ||||
|     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); | ||||
|     while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { | ||||
|         // Render view_port;
 | ||||
|         view_port = *ViewPortArray_ref(it); | ||||
|     while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) { | ||||
|         ViewPort* 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; | ||||
|             // Recalculate next position
 | ||||
|             right_used += (width + 2); | ||||
|             x -= (width + 2); | ||||
|             // Prepare work area background
 | ||||
|             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, | ||||
|                 2, | ||||
|                 canvas_height(gui->canvas) - 2, | ||||
|                 canvas_width(gui->canvas) - 2, | ||||
|                 canvas_height(gui->canvas) - 2); | ||||
| 
 | ||||
|                 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 + 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); | ||||
|         } | ||||
|         ViewPortArray_next(it); | ||||
|     } | ||||
|     // Draw frame around icons on the right
 | ||||
|     if(right_used) { | ||||
|         canvas_frame_set( | ||||
|             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( | ||||
|             gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); | ||||
|         canvas_draw_line( | ||||
|             gui->canvas, | ||||
|             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_width(gui->canvas) - 2, | ||||
|             canvas_height(gui->canvas) - 2); | ||||
|     } | ||||
| 
 | ||||
|     // Left side
 | ||||
|     x = 0; | ||||
|     x = 2; | ||||
|     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); | ||||
|     while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { | ||||
|         ViewPort* 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; | ||||
| 
 | ||||
|             // Prepare work area background
 | ||||
|             canvas_frame_set( | ||||
|                 gui->canvas, 0, GUI_STATUS_BAR_Y, x + width + 5, GUI_STATUS_BAR_HEIGHT); | ||||
|             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, | ||||
|                 2, | ||||
|                 canvas_height(gui->canvas) - 2, | ||||
|                 canvas_width(gui->canvas) - 2, | ||||
|                 canvas_height(gui->canvas) - 2); | ||||
| 
 | ||||
|             canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width + 5, GUI_STATUS_BAR_HEIGHT); | ||||
| 
 | ||||
|                 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, 2, 1, width + 2, 10); | ||||
|             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 + 3, GUI_STATUS_BAR_Y + 2, 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); | ||||
| 
 | ||||
|             // Recalculate next position
 | ||||
|             left_used += (width + 2); | ||||
|             x += (width + 2); | ||||
|         } | ||||
|         ViewPortArray_next(it); | ||||
|     } | ||||
| 
 | ||||
|     // Extra notification
 | ||||
|     if(need_attention) { | ||||
|         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( | ||||
|             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, | ||||
|             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_width(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) { | ||||
|     UNUSED(p); | ||||
|     Gui* gui = gui_alloc(); | ||||
| 
 | ||||
|     furi_record_create("gui", gui); | ||||
|  | ||||
| @ -10,4 +10,4 @@ uint8_t icon_get_height(const Icon* instance) { | ||||
| 
 | ||||
| const uint8_t* icon_get_data(const Icon* instance) { | ||||
|     return instance->frames[0]; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -39,4 +39,4 @@ const uint8_t* icon_get_data(const Icon* instance); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -331,7 +331,7 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) { | ||||
|             ButtonMenuItemArray_it_t it; | ||||
|             for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); | ||||
|                 ButtonMenuItemArray_next(it), ++item_position) { | ||||
|                 if(ButtonMenuItemArray_cref(it)->index == index) { | ||||
|                 if((uint32_t)ButtonMenuItemArray_cref(it)->index == index) { | ||||
|                     model->position = item_position; | ||||
|                     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) { | ||||
|     with_view_model( | ||||
|         button_panel->view, (ButtonPanelModel * model) { | ||||
|             size_t new_selected_item_x = model->selected_item_x; | ||||
|             size_t new_selected_item_y = model->selected_item_y; | ||||
|             uint16_t new_selected_item_x = model->selected_item_x; | ||||
|             uint16_t new_selected_item_y = model->selected_item_y; | ||||
|             size_t i; | ||||
| 
 | ||||
|             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) { | ||||
|     with_view_model( | ||||
|         button_panel->view, (ButtonPanelModel * model) { | ||||
|             size_t new_selected_item_x = model->selected_item_x; | ||||
|             size_t new_selected_item_y = model->selected_item_y; | ||||
|             uint16_t new_selected_item_x = model->selected_item_x; | ||||
|             uint16_t new_selected_item_y = model->selected_item_y; | ||||
|             size_t i; | ||||
| 
 | ||||
|             if(new_selected_item_x >= (model->reserve_x - 1)) return false; | ||||
|  | ||||
| @ -66,4 +66,4 @@ void byte_input_set_header_text(ByteInput* byte_input, const char* text); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -6,10 +6,13 @@ struct EmptyScreen { | ||||
| }; | ||||
| 
 | ||||
| static void empty_screen_view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     UNUSED(_model); | ||||
|     canvas_clear(canvas); | ||||
| } | ||||
| 
 | ||||
| static bool empty_screen_view_input_callback(InputEvent* event, void* context) { | ||||
|     UNUSED(event); | ||||
|     UNUSED(context); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -38,4 +38,4 @@ View* empty_screen_get_view(EmptyScreen* empty_screen); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -28,4 +28,4 @@ void file_select_set_selected_file(FileSelect* file_select, const char* filename | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -34,6 +34,7 @@ static void loading_draw_callback(Canvas* canvas, void* _model) { | ||||
| } | ||||
| 
 | ||||
| static bool loading_input_callback(InputEvent* event, void* context) { | ||||
|     UNUSED(event); | ||||
|     furi_assert(context); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| @ -87,7 +87,7 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { | ||||
|         model->scroll_num = line_num - 4; | ||||
|         model->scroll_pos = line_num - 5; | ||||
|     } else { | ||||
|         model->scroll_num = MAX(line_num - 4, 0); | ||||
|         model->scroll_num = MAX(line_num - 4, 0u); | ||||
|         model->scroll_pos = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -122,15 +122,15 @@ static const TextInputKey* get_row(uint8_t row_index) { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| static const bool char_is_lowercase(char letter) { | ||||
| static bool char_is_lowercase(char letter) { | ||||
|     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)) { | ||||
|         return (letter - 0x20); | ||||
|     } 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) { | ||||
|     UNUSED(text_input); | ||||
|     if(model->selected_row > 0) { | ||||
|         model->selected_row--; | ||||
|         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) { | ||||
|     UNUSED(text_input); | ||||
|     if(model->selected_row < keyboard_row_count - 1) { | ||||
|         model->selected_row++; | ||||
|         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) { | ||||
|     UNUSED(text_input); | ||||
|     if(model->selected_column > 0) { | ||||
|         model->selected_column--; | ||||
|     } 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) { | ||||
|     UNUSED(text_input); | ||||
|     if(model->selected_column < get_row_size(model->selected_row) - 1) { | ||||
|         model->selected_column++; | ||||
|     } else { | ||||
|  | ||||
| @ -19,4 +19,4 @@ bool validator_is_file_callback(const char* text, string_t error, void* context) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -364,6 +364,7 @@ void variable_item_list_set_enter_callback( | ||||
|     furi_assert(callback); | ||||
|     with_view_model( | ||||
|         variable_item_list->view, (VariableItemListModel * model) { | ||||
|             UNUSED(model); | ||||
|             variable_item_list->callback = callback; | ||||
|             variable_item_list->context = context; | ||||
|             return false; | ||||
|  | ||||
| @ -126,6 +126,7 @@ void view_commit_model(View* view, bool update) { | ||||
| } | ||||
| 
 | ||||
| void view_icon_animation_callback(IconAnimation* instance, void* context) { | ||||
|     UNUSED(instance); | ||||
|     furi_assert(context); | ||||
|     View* view = context; | ||||
|     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) { | ||||
|     UNUSED(context); | ||||
|     string_t cmd; | ||||
|     string_init(cmd); | ||||
| 
 | ||||
| @ -268,6 +269,7 @@ void onewire_cli_print_usage() { | ||||
| }; | ||||
| 
 | ||||
| static void onewire_cli_search(Cli* cli) { | ||||
|     UNUSED(cli); | ||||
|     OneWireHost* onewire = onewire_host_alloc(); | ||||
|     uint8_t address[8]; | ||||
|     bool done = false; | ||||
| @ -297,6 +299,7 @@ static void onewire_cli_search(Cli* cli) { | ||||
| } | ||||
| 
 | ||||
| void onewire_cli(Cli* cli, string_t args, void* context) { | ||||
|     UNUSED(context); | ||||
|     string_t cmd; | ||||
|     string_init(cmd); | ||||
| 
 | ||||
| @ -311,4 +314,4 @@ void onewire_cli(Cli* cli, string_t args, void* context) { | ||||
|     } | ||||
| 
 | ||||
|     string_clear(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); | ||||
| }; | ||||
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