[FL-2216, FL-2233] Archive fixes (#987)
* archive: badusb, u2f and various fixes * archive: delete confirmation * badusb: removed empty string check * string pointer check * FuriHal: insomnia overflow assert, fix double insomnia exit in ble. BadUsb: fix uncommitted model. * view update fixes in gpio, badusb, u2f Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									df2d1ad13f
								
							
						
					
					
						commit
						2a52d2d620
					
				| @ -39,6 +39,10 @@ ArchiveApp* archive_alloc() { | |||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
|         archive->view_dispatcher, ArchiveViewTextInput, text_input_get_view(archive->text_input)); |         archive->view_dispatcher, ArchiveViewTextInput, text_input_get_view(archive->text_input)); | ||||||
| 
 | 
 | ||||||
|  |     archive->widget = widget_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         archive->view_dispatcher, ArchiveViewWidget, widget_get_view(archive->widget)); | ||||||
|  | 
 | ||||||
|     return archive; |     return archive; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -47,6 +51,8 @@ void archive_free(ArchiveApp* archive) { | |||||||
| 
 | 
 | ||||||
|     view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewBrowser); |     view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewBrowser); | ||||||
|     view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewTextInput); |     view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewTextInput); | ||||||
|  |     view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewWidget); | ||||||
|  |     widget_free(archive->widget); | ||||||
|     view_dispatcher_free(archive->view_dispatcher); |     view_dispatcher_free(archive->view_dispatcher); | ||||||
|     scene_manager_free(archive->scene_manager); |     scene_manager_free(archive->scene_manager); | ||||||
|     browser_free(archive->browser); |     browser_free(archive->browser); | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
| #include <gui/view_dispatcher.h> | #include <gui/view_dispatcher.h> | ||||||
| #include <gui/scene_manager.h> | #include <gui/scene_manager.h> | ||||||
| #include <gui/modules/text_input.h> | #include <gui/modules/text_input.h> | ||||||
|  | #include <gui/modules/widget.h> | ||||||
| #include <loader/loader.h> | #include <loader/loader.h> | ||||||
| 
 | 
 | ||||||
| #include "views/archive_browser_view.h" | #include "views/archive_browser_view.h" | ||||||
| @ -15,6 +16,7 @@ | |||||||
| typedef enum { | typedef enum { | ||||||
|     ArchiveViewBrowser, |     ArchiveViewBrowser, | ||||||
|     ArchiveViewTextInput, |     ArchiveViewTextInput, | ||||||
|  |     ArchiveViewWidget, | ||||||
|     ArchiveViewTotal, |     ArchiveViewTotal, | ||||||
| } ArchiveViewEnum; | } ArchiveViewEnum; | ||||||
| 
 | 
 | ||||||
| @ -24,6 +26,7 @@ struct ArchiveApp { | |||||||
|     SceneManager* scene_manager; |     SceneManager* scene_manager; | ||||||
|     ArchiveBrowserView* browser; |     ArchiveBrowserView* browser; | ||||||
|     TextInput* text_input; |     TextInput* text_input; | ||||||
|  |     Widget* widget; | ||||||
|     char text_store[MAX_NAME_LEN]; |     char text_store[MAX_NAME_LEN]; | ||||||
|     char file_extension[MAX_EXT_LEN + 1]; |     char file_extension[MAX_EXT_LEN + 1]; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										74
									
								
								applications/archive/helpers/archive_apps.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								applications/archive/helpers/archive_apps.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | #include "archive_files.h" | ||||||
|  | #include "archive_apps.h" | ||||||
|  | #include "archive_browser.h" | ||||||
|  | 
 | ||||||
|  | static const char* known_apps[] = { | ||||||
|  |     [ArchiveAppTypeU2f] = "u2f", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 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) { | ||||||
|  |             return i; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return ArchiveAppTypeUnknown; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool archive_app_is_available(void* context, const char* path) { | ||||||
|  |     furi_assert(path); | ||||||
|  | 
 | ||||||
|  |     ArchiveAppTypeEnum app = archive_get_app_type(path); | ||||||
|  | 
 | ||||||
|  |     if(app == ArchiveAppTypeU2f) { | ||||||
|  |         FileWorker* file_worker = file_worker_alloc(true); | ||||||
|  |         bool file_exists = false; | ||||||
|  |         file_worker_is_file_exist(file_worker, "/any/u2f/key.u2f", &file_exists); | ||||||
|  |         if(file_exists) { | ||||||
|  |             file_worker_is_file_exist(file_worker, "/any/u2f/cnt.u2f", &file_exists); | ||||||
|  |         } | ||||||
|  |         file_worker_free(file_worker); | ||||||
|  |         return file_exists; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool archive_app_read_dir(void* context, const char* path) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     furi_assert(path); | ||||||
|  |     ArchiveBrowserView* browser = context; | ||||||
|  | 
 | ||||||
|  |     ArchiveAppTypeEnum app = archive_get_app_type(path); | ||||||
|  | 
 | ||||||
|  |     if(app == ArchiveAppTypeU2f) { | ||||||
|  |         archive_add_app_item(browser, "/app:u2f/U2F Token"); | ||||||
|  |         return true; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void archive_app_delete_file(void* context, const char* path) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     furi_assert(path); | ||||||
|  |     ArchiveBrowserView* browser = context; | ||||||
|  | 
 | ||||||
|  |     ArchiveAppTypeEnum app = archive_get_app_type(path); | ||||||
|  |     bool res = false; | ||||||
|  | 
 | ||||||
|  |     if(app == ArchiveAppTypeU2f) { | ||||||
|  |         FileWorker* file_worker = file_worker_alloc(true); | ||||||
|  |         res = file_worker_remove(file_worker, "/any/u2f/key.u2f"); | ||||||
|  |         res |= file_worker_remove(file_worker, "/any/u2f/cnt.u2f"); | ||||||
|  |         file_worker_free(file_worker); | ||||||
|  | 
 | ||||||
|  |         if(archive_is_favorite("/app:u2f/U2F Token")) { | ||||||
|  |             archive_favorites_delete("/app:u2f/U2F Token"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(res) { | ||||||
|  |         archive_file_array_rm_selected(browser); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								applications/archive/helpers/archive_apps.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								applications/archive/helpers/archive_apps.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     ArchiveAppTypeU2f, | ||||||
|  |     ArchiveAppTypeUnknown, | ||||||
|  |     ArchiveAppsTotal, | ||||||
|  | } ArchiveAppTypeEnum; | ||||||
|  | 
 | ||||||
|  | static const ArchiveFileTypeEnum app_file_types[] = { | ||||||
|  |     [ArchiveAppTypeU2f] = ArchiveFileTypeU2f, | ||||||
|  |     [ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline const ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { | ||||||
|  |     return app_file_types[app]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ArchiveAppTypeEnum archive_get_app_type(const char* path); | ||||||
|  | bool archive_app_is_available(void* context, const char* path); | ||||||
|  | bool archive_app_read_dir(void* context, const char* path); | ||||||
|  | void archive_app_delete_file(void* context, const char* path); | ||||||
| @ -1,5 +1,7 @@ | |||||||
|  | #include "archive_files.h" | ||||||
|  | #include "archive_apps.h" | ||||||
| #include "archive_browser.h" | #include "archive_browser.h" | ||||||
| #include "math.h" | #include <math.h> | ||||||
| 
 | 
 | ||||||
| void archive_update_offset(ArchiveBrowserView* browser) { | void archive_update_offset(ArchiveBrowserView* browser) { | ||||||
|     furi_assert(browser); |     furi_assert(browser); | ||||||
| @ -177,24 +179,53 @@ void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { | |||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void archive_add_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name) { | void archive_add_app_item(ArchiveBrowserView* browser, const char* name) { | ||||||
|  |     furi_assert(browser); | ||||||
|  |     furi_assert(name); | ||||||
|  | 
 | ||||||
|  |     ArchiveFile_t item; | ||||||
|  | 
 | ||||||
|  |     string_t full_name; | ||||||
|  | 
 | ||||||
|  |     string_init_set(full_name, browser->path); | ||||||
|  |     string_cat_printf(full_name, "/%s", name); | ||||||
|  | 
 | ||||||
|  |     char* app_name = strchr(string_get_cstr(full_name), ':'); | ||||||
|  |     if(app_name == NULL) { | ||||||
|  |         string_clear(full_name); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ArchiveFile_t_init(&item); | ||||||
|  |     string_init_set_str(item.name, name); | ||||||
|  |     set_file_type(&item, NULL, app_name + 1, true); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|  |             files_array_push_back(model->files, item); | ||||||
|  |             return false; | ||||||
|  |         }); | ||||||
|  |     ArchiveFile_t_clear(&item); | ||||||
|  |     string_clear(full_name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void archive_add_file_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name) { | ||||||
|     furi_assert(browser); |     furi_assert(browser); | ||||||
|     furi_assert(file_info); |     furi_assert(file_info); | ||||||
|     furi_assert(name); |     furi_assert(name); | ||||||
| 
 | 
 | ||||||
|     ArchiveFile_t item; |     ArchiveFile_t item; | ||||||
| 
 | 
 | ||||||
|     if(filter_by_extension(file_info, get_tab_ext(archive_get_tab(browser)), name)) { |     if(filter_by_extension(file_info, archive_get_tab_ext(archive_get_tab(browser)), name)) { | ||||||
|         ArchiveFile_t_init(&item); |         ArchiveFile_t_init(&item); | ||||||
|         string_init_set_str(item.name, name); |         string_init_set_str(item.name, name); | ||||||
|         set_file_type(&item, file_info); |         set_file_type(&item, file_info, archive_get_path(browser), false); | ||||||
| 
 | 
 | ||||||
|         with_view_model( |         with_view_model( | ||||||
|             browser->view, (ArchiveBrowserViewModel * model) { |             browser->view, (ArchiveBrowserViewModel * model) { | ||||||
|                 files_array_push_back(model->files, item); |                 files_array_push_back(model->files, item); | ||||||
|                 return false; |                 return false; | ||||||
|             }); |             }); | ||||||
| 
 |  | ||||||
|         ArchiveFile_t_clear(&item); |         ArchiveFile_t_clear(&item); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -208,8 +239,7 @@ void archive_show_file_menu(ArchiveBrowserView* browser, bool show) { | |||||||
| 
 | 
 | ||||||
|             if(show) { |             if(show) { | ||||||
|                 ArchiveFile_t* selected = files_array_get(model->files, model->idx); |                 ArchiveFile_t* selected = files_array_get(model->files, model->idx); | ||||||
|                 selected->fav = archive_is_favorite( |                 selected->fav = archive_is_favorite("%s", string_get_cstr(selected->name)); | ||||||
|                     "%s/%s", string_get_cstr(browser->path), string_get_cstr(selected->name)); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return true; |             return true; | ||||||
| @ -245,12 +275,18 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { | |||||||
| 
 | 
 | ||||||
|     archive_set_tab(browser, tab); |     archive_set_tab(browser, tab); | ||||||
| 
 | 
 | ||||||
|     if((tab != ArchiveTabFavorites && |     const char* path = archive_get_default_path(tab); | ||||||
|         !archive_dir_empty(browser, archive_get_default_path(tab))) || |     bool tab_empty = true; | ||||||
|        (tab == ArchiveTabFavorites && !archive_favorites_count(browser))) { |     if(tab == ArchiveTabFavorites) { | ||||||
|         if(tab != ArchiveTabBrowser) { |         if(archive_favorites_count(browser) > 0) tab_empty = false; | ||||||
|             archive_switch_tab(browser, key); |     } else if(strncmp(path, "/app:", 5) == 0) { | ||||||
|         } |         if(archive_app_is_available(browser, path)) tab_empty = false; | ||||||
|  |     } else { | ||||||
|  |         if(archive_dir_not_empty(browser, archive_get_default_path(tab))) tab_empty = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if((tab_empty) && (tab != ArchiveTabBrowser)) { | ||||||
|  |         archive_switch_tab(browser, key); | ||||||
|     } else { |     } else { | ||||||
|         with_view_model( |         with_view_model( | ||||||
|             browser->view, (ArchiveBrowserViewModel * model) { |             browser->view, (ArchiveBrowserViewModel * model) { | ||||||
| @ -277,8 +313,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { | |||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|     string_cat(browser->path, "/"); |     string_set(browser->path, name); | ||||||
|     string_cat(browser->path, name); |  | ||||||
| 
 | 
 | ||||||
|     archive_switch_dir(browser, string_get_cstr(browser->path)); |     archive_switch_dir(browser, string_get_cstr(browser->path)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,6 +11,8 @@ static const char* tab_default_paths[] = { | |||||||
|     [ArchiveTabSubGhz] = "/any/subghz", |     [ArchiveTabSubGhz] = "/any/subghz", | ||||||
|     [ArchiveTabLFRFID] = "/any/lfrfid", |     [ArchiveTabLFRFID] = "/any/lfrfid", | ||||||
|     [ArchiveTabIrda] = "/any/irda", |     [ArchiveTabIrda] = "/any/irda", | ||||||
|  |     [ArchiveTabBadUsb] = "/any/badusb", | ||||||
|  |     [ArchiveTabU2f] = "/app:u2f", | ||||||
|     [ArchiveTabBrowser] = "/any", |     [ArchiveTabBrowser] = "/any", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -20,30 +22,37 @@ static const char* known_ext[] = { | |||||||
|     [ArchiveFileTypeSubGhz] = ".sub", |     [ArchiveFileTypeSubGhz] = ".sub", | ||||||
|     [ArchiveFileTypeLFRFID] = ".rfid", |     [ArchiveFileTypeLFRFID] = ".rfid", | ||||||
|     [ArchiveFileTypeIrda] = ".ir", |     [ArchiveFileTypeIrda] = ".ir", | ||||||
|  |     [ArchiveFileTypeBadUsb] = ".txt", | ||||||
|  |     [ArchiveFileTypeU2f] = "?", | ||||||
|  |     [ArchiveFileTypeFolder] = "?", | ||||||
|  |     [ArchiveFileTypeUnknown] = "*", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static inline const char* get_tab_ext(ArchiveTabEnum tab) { | static const ArchiveFileTypeEnum known_type[] = { | ||||||
|     switch(tab) { |     [ArchiveTabFavorites] = ArchiveFileTypeUnknown, | ||||||
|     case ArchiveTabIButton: |     [ArchiveTabIButton] = ArchiveFileTypeIButton, | ||||||
|         return known_ext[ArchiveFileTypeIButton]; |     [ArchiveTabNFC] = ArchiveFileTypeNFC, | ||||||
|     case ArchiveTabNFC: |     [ArchiveTabSubGhz] = ArchiveFileTypeSubGhz, | ||||||
|         return known_ext[ArchiveFileTypeNFC]; |     [ArchiveTabLFRFID] = ArchiveFileTypeLFRFID, | ||||||
|     case ArchiveTabSubGhz: |     [ArchiveTabIrda] = ArchiveFileTypeIrda, | ||||||
|         return known_ext[ArchiveFileTypeSubGhz]; |     [ArchiveTabBadUsb] = ArchiveFileTypeBadUsb, | ||||||
|     case ArchiveTabLFRFID: |     [ArchiveTabU2f] = ArchiveFileTypeU2f, | ||||||
|         return known_ext[ArchiveFileTypeLFRFID]; |     [ArchiveTabBrowser] = ArchiveFileTypeUnknown, | ||||||
|     case ArchiveTabIrda: | }; | ||||||
|         return known_ext[ArchiveFileTypeIrda]; | 
 | ||||||
|     default: | static inline const ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { | ||||||
|         return "*"; |     return known_type[tab]; | ||||||
|     } | } | ||||||
|  | 
 | ||||||
|  | static inline const char* archive_get_tab_ext(ArchiveTabEnum tab) { | ||||||
|  |     return known_ext[archive_get_tab_filetype(tab)]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline const char* archive_get_default_path(ArchiveTabEnum tab) { | static inline const char* archive_get_default_path(ArchiveTabEnum tab) { | ||||||
|     return tab_default_paths[tab]; |     return tab_default_paths[tab]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool is_known_app(ArchiveFileTypeEnum type) { | inline bool archive_is_known_app(ArchiveFileTypeEnum type) { | ||||||
|     return (type != ArchiveFileTypeFolder && type != ArchiveFileTypeUnknown); |     return (type != ArchiveFileTypeFolder && type != ArchiveFileTypeUnknown); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -62,7 +71,8 @@ uint8_t archive_get_depth(ArchiveBrowserView* browser); | |||||||
| const char* archive_get_path(ArchiveBrowserView* browser); | const char* archive_get_path(ArchiveBrowserView* browser); | ||||||
| const char* archive_get_name(ArchiveBrowserView* browser); | const char* archive_get_name(ArchiveBrowserView* browser); | ||||||
| 
 | 
 | ||||||
| void archive_add_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name); | void archive_add_app_item(ArchiveBrowserView* browser, const char* name); | ||||||
|  | void archive_add_file_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name); | ||||||
| void archive_show_file_menu(ArchiveBrowserView* browser, bool show); | void archive_show_file_menu(ArchiveBrowserView* browser, bool show); | ||||||
| void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active); | void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "archive_favorites.h" | #include "archive_favorites.h" | ||||||
|  | #include "archive_files.h" | ||||||
|  | #include "archive_apps.h" | ||||||
| #include "archive_browser.h" | #include "archive_browser.h" | ||||||
| 
 | 
 | ||||||
| uint16_t archive_favorites_count(void* context) { | uint16_t archive_favorites_count(void* context) { | ||||||
| @ -46,10 +48,16 @@ static bool archive_favourites_rescan() { | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             bool file_exists = false; |             if(string_search(buffer, "/app:") == 0) { | ||||||
|             file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); |                 if(archive_app_is_available(NULL, string_get_cstr(buffer))) { | ||||||
|             if(file_exists) { |                     archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); | ||||||
|                 archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); |                 } | ||||||
|  |             } else { | ||||||
|  |                 bool file_exists = false; | ||||||
|  |                 file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); | ||||||
|  |                 if(file_exists) { | ||||||
|  |                     archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -88,13 +96,22 @@ bool archive_favorites_read(void* context) { | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             bool file_exists = false; |             if(string_search(buffer, "/app:") == 0) { | ||||||
|             file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); |                 if(archive_app_is_available(browser, string_get_cstr(buffer))) { | ||||||
|  |                     archive_add_app_item(browser, string_get_cstr(buffer)); | ||||||
|  |                 } else { | ||||||
|  |                     need_refresh = true; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 bool file_exists = false; | ||||||
|  |                 file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); | ||||||
|  | 
 | ||||||
|  |                 if(file_exists) | ||||||
|  |                     archive_add_file_item(browser, &file_info, string_get_cstr(buffer)); | ||||||
|  |                 else | ||||||
|  |                     need_refresh = true; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             if(file_exists) |  | ||||||
|                 archive_add_item(browser, &file_info, string_get_cstr(buffer)); |  | ||||||
|             else |  | ||||||
|                 need_refresh = true; |  | ||||||
|             string_reset(buffer); |             string_reset(buffer); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -185,8 +202,7 @@ bool archive_is_favorite(const char* format, ...) { | |||||||
|     return found; |     return found; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool archive_favorites_rename(const char* file_path, const char* src, const char* dst) { | bool archive_favorites_rename(const char* src, const char* dst) { | ||||||
|     furi_assert(file_path); |  | ||||||
|     furi_assert(src); |     furi_assert(src); | ||||||
|     furi_assert(dst); |     furi_assert(dst); | ||||||
| 
 | 
 | ||||||
| @ -198,7 +214,7 @@ bool archive_favorites_rename(const char* file_path, const char* src, const char | |||||||
|     string_init(buffer); |     string_init(buffer); | ||||||
|     string_init(path); |     string_init(path); | ||||||
| 
 | 
 | ||||||
|     string_printf(path, "%s/%s", file_path, src); |     string_printf(path, "%s", src); | ||||||
|     bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); |     bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); | ||||||
| 
 | 
 | ||||||
|     if(result) { |     if(result) { | ||||||
|  | |||||||
| @ -8,6 +8,6 @@ uint16_t archive_favorites_count(void* context); | |||||||
| bool archive_favorites_read(void* context); | bool archive_favorites_read(void* context); | ||||||
| bool archive_favorites_delete(const char* format, ...); | bool archive_favorites_delete(const char* format, ...); | ||||||
| bool archive_is_favorite(const char* format, ...); | bool archive_is_favorite(const char* format, ...); | ||||||
| bool archive_favorites_rename(const char* file_path, const char* src, const char* dst); | bool archive_favorites_rename(const char* src, const char* dst); | ||||||
| void archive_add_to_favorites(const char* file_path); | void archive_add_to_favorites(const char* file_path); | ||||||
| void archive_favorites_save(void* context); | void archive_favorites_save(void* context); | ||||||
|  | |||||||
| @ -1,8 +1,11 @@ | |||||||
| #include "archive_files.h" | #include "archive_files.h" | ||||||
|  | #include "archive_apps.h" | ||||||
| #include "archive_browser.h" | #include "archive_browser.h" | ||||||
| 
 | 
 | ||||||
| #define TAG "Archive" | #define TAG "Archive" | ||||||
| 
 | 
 | ||||||
|  | #define ASSETS_DIR "assets" | ||||||
|  | 
 | ||||||
| bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name) { | bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name) { | ||||||
|     furi_assert(file_info); |     furi_assert(file_info); | ||||||
|     furi_assert(tab_ext); |     furi_assert(tab_ext); | ||||||
| @ -15,7 +18,11 @@ bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* n | |||||||
|     } else if(strstr(name, tab_ext) != NULL) { |     } else if(strstr(name, tab_ext) != NULL) { | ||||||
|         result = true; |         result = true; | ||||||
|     } else if(file_info->flags & FSF_DIRECTORY) { |     } else if(file_info->flags & FSF_DIRECTORY) { | ||||||
|         result = true; |         if(strstr(name, ASSETS_DIR) != NULL) { | ||||||
|  |             result = false; // Skip assets folder in all tabs except browser
 | ||||||
|  |         } else { | ||||||
|  |             result = true; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return result; |     return result; | ||||||
| @ -38,21 +45,36 @@ void archive_get_file_extension(char* name, char* ext) { | |||||||
|         strncpy(ext, dot, MAX_EXT_LEN); |         strncpy(ext, dot, MAX_EXT_LEN); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void set_file_type(ArchiveFile_t* file, FileInfo* file_info) { | void set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* path, bool is_app) { | ||||||
|     furi_assert(file); |     furi_assert(file); | ||||||
|     furi_assert(file_info); |  | ||||||
| 
 | 
 | ||||||
|     for(size_t i = 0; i < SIZEOF_ARRAY(known_ext); i++) { |     file->is_app = is_app; | ||||||
|         if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { |     if(is_app) { | ||||||
|             file->type = i; |         file->type = archive_get_app_filetype(archive_get_app_type(path)); | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(file_info->flags & FSF_DIRECTORY) { |  | ||||||
|         file->type = ArchiveFileTypeFolder; |  | ||||||
|     } else { |     } else { | ||||||
|         file->type = ArchiveFileTypeUnknown; |         furi_assert(file_info); | ||||||
|  | 
 | ||||||
|  |         for(size_t i = 0; i < SIZEOF_ARRAY(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) { | ||||||
|  |                     if(string_search_str(file->name, archive_get_default_path(ArchiveTabBadUsb)) == | ||||||
|  |                        0) { | ||||||
|  |                         file->type = i; | ||||||
|  |                         return; // *.txt file is a BadUSB script only if it is in BadUSB folder
 | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     file->type = i; | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(file_info->flags & FSF_DIRECTORY) { | ||||||
|  |             file->type = ArchiveFileTypeFolder; | ||||||
|  |         } else { | ||||||
|  |             file->type = ArchiveFileTypeUnknown; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -63,17 +85,21 @@ bool archive_get_filenames(void* context, const char* path) { | |||||||
|     ArchiveBrowserView* browser = context; |     ArchiveBrowserView* browser = context; | ||||||
|     archive_file_array_rm_all(browser); |     archive_file_array_rm_all(browser); | ||||||
| 
 | 
 | ||||||
|     if(archive_get_tab(browser) != ArchiveTabFavorites) { |     if(archive_get_tab(browser) == ArchiveTabFavorites) { | ||||||
|         res = archive_read_dir(browser, path); |  | ||||||
|     } else { |  | ||||||
|         res = archive_favorites_read(browser); |         res = archive_favorites_read(browser); | ||||||
|  |     } else if(strncmp(path, "/app:", 5) == 0) { | ||||||
|  |         res = archive_app_read_dir(browser, path); | ||||||
|  |     } else { | ||||||
|  |         res = archive_read_dir(browser, path); | ||||||
|     } |     } | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool archive_dir_empty(void* context, const char* path) { // can be simpler?
 | bool archive_dir_not_empty(void* context, const char* path) { // can be simpler?
 | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
| 
 | 
 | ||||||
|  |     ArchiveBrowserView* browser = context; | ||||||
|  | 
 | ||||||
|     FileInfo file_info; |     FileInfo file_info; | ||||||
|     Storage* fs_api = furi_record_open("storage"); |     Storage* fs_api = furi_record_open("storage"); | ||||||
|     File* directory = storage_file_alloc(fs_api); |     File* directory = storage_file_alloc(fs_api); | ||||||
| @ -92,8 +118,11 @@ bool archive_dir_empty(void* context, const char* path) { // can be simpler? | |||||||
|         } |         } | ||||||
|         if(files_found) { |         if(files_found) { | ||||||
|             break; |             break; | ||||||
|         } else if(storage_file_get_error(directory) == FSE_OK) { |         } else if((storage_file_get_error(directory) == FSE_OK) && (name[0])) { | ||||||
|             files_found = name[0]; |             if(filter_by_extension( | ||||||
|  |                    &file_info, archive_get_tab_ext(archive_get_tab(browser)), name)) { | ||||||
|  |                 files_found = true; | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| @ -114,6 +143,8 @@ bool archive_read_dir(void* context, const char* path) { | |||||||
|     Storage* fs_api = furi_record_open("storage"); |     Storage* fs_api = furi_record_open("storage"); | ||||||
|     File* directory = storage_file_alloc(fs_api); |     File* directory = storage_file_alloc(fs_api); | ||||||
|     char name[MAX_NAME_LEN]; |     char name[MAX_NAME_LEN]; | ||||||
|  |     snprintf(name, MAX_NAME_LEN, "%s/", path); | ||||||
|  |     size_t path_len = strlen(name); | ||||||
|     size_t files_cnt = 0; |     size_t files_cnt = 0; | ||||||
| 
 | 
 | ||||||
|     if(!storage_dir_open(directory, path)) { |     if(!storage_dir_open(directory, path)) { | ||||||
| @ -123,13 +154,14 @@ bool archive_read_dir(void* context, const char* path) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     while(1) { |     while(1) { | ||||||
|         if(!storage_dir_read(directory, &file_info, name, MAX_NAME_LEN)) { |         if(!storage_dir_read(directory, &file_info, &name[path_len], MAX_NAME_LEN - path_len)) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         if(files_cnt > MAX_FILES) { |         if(files_cnt > MAX_FILES) { | ||||||
|             break; |             break; | ||||||
|         } else if(storage_file_get_error(directory) == FSE_OK) { |         } else if(storage_file_get_error(directory) == FSE_OK) { | ||||||
|             archive_add_item(browser, &file_info, name); |             archive_add_file_item(browser, &file_info, name); | ||||||
|             ++files_cnt; |             ++files_cnt; | ||||||
|         } else { |         } else { | ||||||
|             storage_dir_close(directory); |             storage_dir_close(directory); | ||||||
|  | |||||||
| @ -9,29 +9,38 @@ typedef enum { | |||||||
|     ArchiveFileTypeSubGhz, |     ArchiveFileTypeSubGhz, | ||||||
|     ArchiveFileTypeLFRFID, |     ArchiveFileTypeLFRFID, | ||||||
|     ArchiveFileTypeIrda, |     ArchiveFileTypeIrda, | ||||||
|  |     ArchiveFileTypeBadUsb, | ||||||
|  |     ArchiveFileTypeU2f, | ||||||
|     ArchiveFileTypeFolder, |     ArchiveFileTypeFolder, | ||||||
|     ArchiveFileTypeUnknown, |     ArchiveFileTypeUnknown, | ||||||
|     AppIdTotal, |     ArchiveFileTypesTotal, | ||||||
| } ArchiveFileTypeEnum; | } ArchiveFileTypeEnum; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     string_t name; |     string_t name; | ||||||
|     ArchiveFileTypeEnum type; |     ArchiveFileTypeEnum type; | ||||||
|     bool fav; |     bool fav; | ||||||
|  |     bool is_app; | ||||||
| } ArchiveFile_t; | } ArchiveFile_t; | ||||||
| 
 | 
 | ||||||
| static void ArchiveFile_t_init(ArchiveFile_t* obj) { | static void ArchiveFile_t_init(ArchiveFile_t* obj) { | ||||||
|     obj->type = ArchiveFileTypeUnknown; |     obj->type = ArchiveFileTypeUnknown; | ||||||
|  |     obj->is_app = false; | ||||||
|  |     obj->fav = false; | ||||||
|     string_init(obj->name); |     string_init(obj->name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { | static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { | ||||||
|     obj->type = src->type; |     obj->type = src->type; | ||||||
|  |     obj->is_app = src->is_app; | ||||||
|  |     obj->fav = src->fav; | ||||||
|     string_init_set(obj->name, src->name); |     string_init_set(obj->name, src->name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { | static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { | ||||||
|     obj->type = src->type; |     obj->type = src->type; | ||||||
|  |     obj->is_app = src->is_app; | ||||||
|  |     obj->fav = src->fav; | ||||||
|     string_set(obj->name, src->name); |     string_set(obj->name, src->name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -48,11 +57,11 @@ ARRAY_DEF( | |||||||
|      CLEAR(API_2(ArchiveFile_t_clear)))) |      CLEAR(API_2(ArchiveFile_t_clear)))) | ||||||
| 
 | 
 | ||||||
| bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name); | bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name); | ||||||
| void set_file_type(ArchiveFile_t* file, FileInfo* file_info); | void set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* path, bool is_app); | ||||||
| void archive_trim_file_path(char* name, bool ext); | void archive_trim_file_path(char* name, bool ext); | ||||||
| void archive_get_file_extension(char* name, char* ext); | void archive_get_file_extension(char* name, char* ext); | ||||||
| bool archive_get_filenames(void* context, const char* path); | bool archive_get_filenames(void* context, const char* path); | ||||||
| bool archive_dir_empty(void* context, const char* path); | bool archive_dir_not_empty(void* context, const char* path); | ||||||
| bool archive_read_dir(void* context, const char* path); | bool archive_read_dir(void* context, const char* path); | ||||||
| void archive_file_append(const char* path, const char* format, ...); | void archive_file_append(const char* path, const char* format, ...); | ||||||
| void archive_delete_file(void* context, const char* format, ...); | void archive_delete_file(void* context, const char* format, ...); | ||||||
| @ -1,5 +1,6 @@ | |||||||
| #include "../archive_i.h" | #include "../archive_i.h" | ||||||
| #include "../helpers/archive_files.h" | #include "../helpers/archive_files.h" | ||||||
|  | #include "../helpers/archive_apps.h" | ||||||
| #include "../helpers/archive_favorites.h" | #include "../helpers/archive_favorites.h" | ||||||
| #include "../helpers/archive_browser.h" | #include "../helpers/archive_browser.h" | ||||||
| #include "../views/archive_browser_view.h" | #include "../views/archive_browser_view.h" | ||||||
| @ -12,29 +13,29 @@ static const char* flipper_app_name[] = { | |||||||
|     [ArchiveFileTypeSubGhz] = "Sub-GHz", |     [ArchiveFileTypeSubGhz] = "Sub-GHz", | ||||||
|     [ArchiveFileTypeLFRFID] = "125 kHz RFID", |     [ArchiveFileTypeLFRFID] = "125 kHz RFID", | ||||||
|     [ArchiveFileTypeIrda] = "Infrared", |     [ArchiveFileTypeIrda] = "Infrared", | ||||||
|  |     [ArchiveFileTypeBadUsb] = "Bad USB", | ||||||
|  |     [ArchiveFileTypeU2f] = "U2F", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void archive_run_in_app( | static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { | ||||||
|     ArchiveBrowserView* browser, |  | ||||||
|     ArchiveFile_t* selected, |  | ||||||
|     bool full_path_provided) { |  | ||||||
|     Loader* loader = furi_record_open("loader"); |     Loader* loader = furi_record_open("loader"); | ||||||
| 
 | 
 | ||||||
|     string_t full_path; |     LoaderStatus status; | ||||||
|     if(!full_path_provided) { |     if(selected->is_app) { | ||||||
|         string_init_printf( |         char* param = strrchr(string_get_cstr(selected->name), '/'); | ||||||
|             full_path, "%s/%s", string_get_cstr(browser->path), string_get_cstr(selected->name)); |         if(param != NULL) { | ||||||
|  |             param++; | ||||||
|  |         } | ||||||
|  |         status = loader_start(loader, flipper_app_name[selected->type], param); | ||||||
|     } else { |     } else { | ||||||
|         string_init_set(full_path, selected->name); |         status = loader_start( | ||||||
|  |             loader, flipper_app_name[selected->type], string_get_cstr(selected->name)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LoaderStatus status = |  | ||||||
|         loader_start(loader, flipper_app_name[selected->type], string_get_cstr(full_path)); |  | ||||||
|     if(status != LoaderStatusOk) { |     if(status != LoaderStatusOk) { | ||||||
|         FURI_LOG_E(TAG, "loader_start failed: %d", status); |         FURI_LOG_E(TAG, "loader_start failed: %d", status); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     string_clear(full_path); |  | ||||||
|     furi_record_close("loader"); |     furi_record_close("loader"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -57,9 +58,8 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|     ArchiveBrowserView* browser = archive->browser; |     ArchiveBrowserView* browser = archive->browser; | ||||||
|     ArchiveFile_t* selected = archive_get_current_file(browser); |     ArchiveFile_t* selected = archive_get_current_file(browser); | ||||||
| 
 | 
 | ||||||
|     const char* path = archive_get_path(browser); |  | ||||||
|     const char* name = archive_get_name(browser); |     const char* name = archive_get_name(browser); | ||||||
|     bool known_app = is_known_app(selected->type); |     bool known_app = archive_is_known_app(selected->type); | ||||||
|     bool favorites = archive_get_tab(browser) == ArchiveTabFavorites; |     bool favorites = archive_get_tab(browser) == ArchiveTabFavorites; | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
| @ -75,7 +75,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|             break; |             break; | ||||||
|         case ArchiveBrowserEventFileMenuRun: |         case ArchiveBrowserEventFileMenuRun: | ||||||
|             if(known_app) { |             if(known_app) { | ||||||
|                 archive_run_in_app(browser, selected, favorites); |                 archive_run_in_app(browser, selected); | ||||||
|             } |             } | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             break; |             break; | ||||||
| @ -85,10 +85,10 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 archive_file_array_rm_selected(browser); |                 archive_file_array_rm_selected(browser); | ||||||
|                 archive_show_file_menu(browser, false); |                 archive_show_file_menu(browser, false); | ||||||
|             } else if(known_app) { |             } else if(known_app) { | ||||||
|                 if(archive_is_favorite("%s/%s", path, name)) { |                 if(archive_is_favorite("%s", name)) { | ||||||
|                     archive_favorites_delete("%s/%s", path, name); |                     archive_favorites_delete("%s", name); | ||||||
|                 } else { |                 } else { | ||||||
|                     archive_file_append(ARCHIVE_FAV_PATH, "%s/%s\n", path, name); |                     archive_file_append(ARCHIVE_FAV_PATH, "%s\n", name); | ||||||
|                 } |                 } | ||||||
|                 archive_show_file_menu(browser, false); |                 archive_show_file_menu(browser, false); | ||||||
|             } |             } | ||||||
| @ -98,18 +98,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|         case ArchiveBrowserEventFileMenuAction: |         case ArchiveBrowserEventFileMenuAction: | ||||||
|             if(favorites) { |             if(favorites) { | ||||||
|                 browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); |                 browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); | ||||||
|             } else if(known_app) { |             } else if((known_app) && (selected->is_app == false)) { | ||||||
|                 scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneRename); |                 scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneRename); | ||||||
|             } |             } | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             break; |             break; | ||||||
|         case ArchiveBrowserEventFileMenuDelete: |         case ArchiveBrowserEventFileMenuDelete: | ||||||
|             if(favorites) { |             scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete); | ||||||
|                 archive_delete_file(browser, "%s", name); |  | ||||||
|             } else { |  | ||||||
|                 archive_delete_file(browser, "%s/%s", path, name); |  | ||||||
|             } |  | ||||||
|             archive_show_file_menu(browser, false); |  | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             break; |             break; | ||||||
|         case ArchiveBrowserEventEnterDir: |         case ArchiveBrowserEventEnterDir: | ||||||
|  | |||||||
| @ -1,2 +1,3 @@ | |||||||
| ADD_SCENE(archive, browser, Browser) | ADD_SCENE(archive, browser, Browser) | ||||||
| ADD_SCENE(archive, rename, Rename) | ADD_SCENE(archive, rename, Rename) | ||||||
|  | ADD_SCENE(archive, delete, Delete) | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								applications/archive/scenes/archive_scene_delete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								applications/archive/scenes/archive_scene_delete.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | #include "../archive_i.h" | ||||||
|  | #include "../helpers/archive_favorites.h" | ||||||
|  | #include "../helpers/archive_files.h" | ||||||
|  | #include "../helpers/archive_apps.h" | ||||||
|  | #include "../helpers/archive_browser.h" | ||||||
|  | 
 | ||||||
|  | #define SCENE_DELETE_CUSTOM_EVENT (0UL) | ||||||
|  | #define MAX_TEXT_INPUT_LEN 22 | ||||||
|  | 
 | ||||||
|  | void archive_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     ArchiveApp* app = (ArchiveApp*)context; | ||||||
|  |     if(type == InputTypeShort) { | ||||||
|  |         view_dispatcher_send_custom_event(app->view_dispatcher, result); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void archive_scene_delete_on_enter(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     ArchiveApp* app = (ArchiveApp*)context; | ||||||
|  | 
 | ||||||
|  |     widget_add_button_element( | ||||||
|  |         app->widget, GuiButtonTypeLeft, "Back", archive_scene_delete_widget_callback, app); | ||||||
|  |     widget_add_button_element( | ||||||
|  |         app->widget, GuiButtonTypeRight, "Delete", archive_scene_delete_widget_callback, app); | ||||||
|  | 
 | ||||||
|  |     ArchiveFile_t* current = archive_get_current_file(app->browser); | ||||||
|  |     strlcpy(app->text_store, string_get_cstr(current->name), MAX_NAME_LEN); | ||||||
|  |     char* name = strrchr(app->text_store, '/'); | ||||||
|  |     if(name != NULL) { | ||||||
|  |         name++; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     char delete_str[64]; | ||||||
|  |     snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", name); | ||||||
|  |     widget_add_text_box_element(app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool archive_scene_delete_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     ArchiveApp* app = (ArchiveApp*)context; | ||||||
|  | 
 | ||||||
|  |     ArchiveBrowserView* browser = app->browser; | ||||||
|  |     ArchiveFile_t* selected = archive_get_current_file(browser); | ||||||
|  |     const char* name = archive_get_name(browser); | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == GuiButtonTypeRight) { | ||||||
|  |             if(selected->is_app) { | ||||||
|  |                 archive_app_delete_file(browser, name); | ||||||
|  |             } else { | ||||||
|  |                 archive_delete_file(browser, "%s", name); | ||||||
|  |             } | ||||||
|  |             archive_show_file_menu(browser, false); | ||||||
|  |             return scene_manager_previous_scene(app->scene_manager); | ||||||
|  |         } else if(event.event == GuiButtonTypeLeft) { | ||||||
|  |             return scene_manager_previous_scene(app->scene_manager); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void archive_scene_delete_on_exit(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     ArchiveApp* app = (ArchiveApp*)context; | ||||||
|  | 
 | ||||||
|  |     widget_reset(app->widget); | ||||||
|  | } | ||||||
| @ -52,7 +52,8 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { | |||||||
|             const char* path = archive_get_path(archive->browser); |             const char* path = archive_get_path(archive->browser); | ||||||
|             const char* name = archive_get_name(archive->browser); |             const char* name = archive_get_name(archive->browser); | ||||||
| 
 | 
 | ||||||
|             string_init_printf(buffer_src, "%s/%s", path, name); |             string_init_printf(buffer_src, "%s", name); | ||||||
|  |             //TODO: take path from src name
 | ||||||
|             string_init_printf(buffer_dst, "%s/%s", path, archive->text_store); |             string_init_printf(buffer_dst, "%s/%s", path, archive->text_store); | ||||||
| 
 | 
 | ||||||
|             // append extension
 |             // append extension
 | ||||||
| @ -64,7 +65,7 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { | |||||||
|             furi_record_close("storage"); |             furi_record_close("storage"); | ||||||
| 
 | 
 | ||||||
|             if(file->fav) { |             if(file->fav) { | ||||||
|                 archive_favorites_rename(path, name, string_get_cstr(buffer_dst)); |                 archive_favorites_rename(name, string_get_cstr(buffer_dst)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             string_clear(buffer_src); |             string_clear(buffer_src); | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ static const char* ArchiveTabNames[] = { | |||||||
|     [ArchiveTabSubGhz] = "Sub-GHz", |     [ArchiveTabSubGhz] = "Sub-GHz", | ||||||
|     [ArchiveTabLFRFID] = "RFID LF", |     [ArchiveTabLFRFID] = "RFID LF", | ||||||
|     [ArchiveTabIrda] = "Infrared", |     [ArchiveTabIrda] = "Infrared", | ||||||
|  |     [ArchiveTabBadUsb] = "Bad USB", | ||||||
|  |     [ArchiveTabU2f] = "U2F", | ||||||
|     [ArchiveTabBrowser] = "Browser"}; |     [ArchiveTabBrowser] = "Browser"}; | ||||||
| 
 | 
 | ||||||
| static const Icon* ArchiveItemIcons[] = { | static const Icon* ArchiveItemIcons[] = { | ||||||
| @ -18,6 +20,8 @@ static const Icon* ArchiveItemIcons[] = { | |||||||
|     [ArchiveFileTypeSubGhz] = &I_sub1_10px, |     [ArchiveFileTypeSubGhz] = &I_sub1_10px, | ||||||
|     [ArchiveFileTypeLFRFID] = &I_125_10px, |     [ArchiveFileTypeLFRFID] = &I_125_10px, | ||||||
|     [ArchiveFileTypeIrda] = &I_ir_10px, |     [ArchiveFileTypeIrda] = &I_ir_10px, | ||||||
|  |     [ArchiveFileTypeBadUsb] = &I_badusb_10px, | ||||||
|  |     [ArchiveFileTypeU2f] = &I_u2f_10px, | ||||||
|     [ArchiveFileTypeFolder] = &I_dir_10px, |     [ArchiveFileTypeFolder] = &I_dir_10px, | ||||||
|     [ArchiveFileTypeUnknown] = &I_unknown_10px, |     [ArchiveFileTypeUnknown] = &I_unknown_10px, | ||||||
| }; | }; | ||||||
| @ -47,15 +51,20 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) { | |||||||
| 
 | 
 | ||||||
|     ArchiveFile_t* selected = files_array_get(model->files, model->idx); |     ArchiveFile_t* selected = files_array_get(model->files, model->idx); | ||||||
| 
 | 
 | ||||||
|     if(!is_known_app(selected->type)) { |     if(!archive_is_known_app(selected->type)) { | ||||||
|         string_set_str(menu[0], "---"); |         string_set_str(menu[0], "---"); | ||||||
|         string_set_str(menu[1], "---"); |         string_set_str(menu[1], "---"); | ||||||
|         string_set_str(menu[2], "---"); |         string_set_str(menu[2], "---"); | ||||||
|     } else if(selected->fav) { |     } else { | ||||||
|  |         if(model->tab_idx == ArchiveTabFavorites) { | ||||||
|  |             string_set_str(menu[2], "Move"); | ||||||
|  |         } else if(selected->is_app) { | ||||||
|  |             string_set_str(menu[2], "---"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) { | ||||||
|         string_set_str(menu[1], "Unpin"); |         string_set_str(menu[1], "Unpin"); | ||||||
|     } else if(model->tab_idx == ArchiveTabFavorites) { |  | ||||||
|         string_set_str(menu[1], "Unpin"); |  | ||||||
|         string_set_str(menu[2], "Move"); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for(size_t i = 0; i < MENU_ITEMS; i++) { |     for(size_t i = 0; i < MENU_ITEMS; i++) { | ||||||
| @ -102,7 +111,7 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { | |||||||
|         ArchiveFile_t* file = files_array_get(model->files, CLAMP(idx, array_size - 1, 0)); |         ArchiveFile_t* file = files_array_get(model->files, CLAMP(idx, array_size - 1, 0)); | ||||||
| 
 | 
 | ||||||
|         strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); |         strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); | ||||||
|         archive_trim_file_path(cstr_buff, is_known_app(file->type)); |         archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); | ||||||
|         string_init_set_str(str_buff, cstr_buff); |         string_init_set_str(str_buff, cstr_buff); | ||||||
|         elements_string_fit_width( |         elements_string_fit_width( | ||||||
|             canvas, str_buff, (scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX) - x_offset); |             canvas, str_buff, (scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX) - x_offset); | ||||||
|  | |||||||
| @ -24,6 +24,8 @@ typedef enum { | |||||||
|     ArchiveTabNFC, |     ArchiveTabNFC, | ||||||
|     ArchiveTabIrda, |     ArchiveTabIrda, | ||||||
|     ArchiveTabIButton, |     ArchiveTabIButton, | ||||||
|  |     ArchiveTabBadUsb, | ||||||
|  |     ArchiveTabU2f, | ||||||
|     ArchiveTabBrowser, |     ArchiveTabBrowser, | ||||||
|     ArchiveTabTotal, |     ArchiveTabTotal, | ||||||
| } ArchiveTabEnum; | } ArchiveTabEnum; | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
|  | #include <lib/toolbox/path.h> | ||||||
| 
 | 
 | ||||||
| static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { | static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
| @ -39,27 +40,34 @@ static bool bad_usb_check_assets() { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BadUsbApp* bad_usb_app_alloc() { | BadUsbApp* bad_usb_app_alloc(char* arg) { | ||||||
|     BadUsbApp* app = furi_alloc(sizeof(BadUsbApp)); |     BadUsbApp* app = furi_alloc(sizeof(BadUsbApp)); | ||||||
| 
 | 
 | ||||||
|  |     if(arg != NULL) { | ||||||
|  |         string_t filename; | ||||||
|  |         string_init(filename); | ||||||
|  |         path_extract_filename_no_ext(arg, filename); | ||||||
|  |         strncpy(app->file_name, string_get_cstr(filename), BAD_USB_FILE_NAME_LEN); | ||||||
|  |         string_clear(filename); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     app->gui = furi_record_open("gui"); |     app->gui = furi_record_open("gui"); | ||||||
|     app->notifications = furi_record_open("notification"); |     app->notifications = furi_record_open("notification"); | ||||||
|     app->dialogs = furi_record_open("dialogs"); |     app->dialogs = furi_record_open("dialogs"); | ||||||
| 
 | 
 | ||||||
|     app->view_dispatcher = view_dispatcher_alloc(); |     app->view_dispatcher = view_dispatcher_alloc(); | ||||||
|     app->scene_manager = scene_manager_alloc(&bad_usb_scene_handlers, app); |  | ||||||
|     view_dispatcher_enable_queue(app->view_dispatcher); |     view_dispatcher_enable_queue(app->view_dispatcher); | ||||||
|  | 
 | ||||||
|  |     app->scene_manager = scene_manager_alloc(&bad_usb_scene_handlers, app); | ||||||
|  | 
 | ||||||
|     view_dispatcher_set_event_callback_context(app->view_dispatcher, app); |     view_dispatcher_set_event_callback_context(app->view_dispatcher, app); | ||||||
|     view_dispatcher_set_tick_event_callback( |     view_dispatcher_set_tick_event_callback( | ||||||
|         app->view_dispatcher, bad_usb_app_tick_event_callback, 500); |         app->view_dispatcher, bad_usb_app_tick_event_callback, 500); | ||||||
| 
 |  | ||||||
|     view_dispatcher_set_custom_event_callback( |     view_dispatcher_set_custom_event_callback( | ||||||
|         app->view_dispatcher, bad_usb_app_custom_event_callback); |         app->view_dispatcher, bad_usb_app_custom_event_callback); | ||||||
|     view_dispatcher_set_navigation_event_callback( |     view_dispatcher_set_navigation_event_callback( | ||||||
|         app->view_dispatcher, bad_usb_app_back_event_callback); |         app->view_dispatcher, bad_usb_app_back_event_callback); | ||||||
| 
 | 
 | ||||||
|     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); |  | ||||||
| 
 |  | ||||||
|     // Custom Widget
 |     // Custom Widget
 | ||||||
|     app->widget = widget_alloc(); |     app->widget = widget_alloc(); | ||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
| @ -69,7 +77,11 @@ BadUsbApp* bad_usb_app_alloc() { | |||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
|         app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); |         app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); | ||||||
| 
 | 
 | ||||||
|     if(bad_usb_check_assets()) { |     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); | ||||||
|  | 
 | ||||||
|  |     if(*app->file_name != '\0') { | ||||||
|  |         scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); | ||||||
|  |     } else if(bad_usb_check_assets()) { | ||||||
|         scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); |         scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); | ||||||
|     } else { |     } else { | ||||||
|         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); |         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); | ||||||
| @ -106,7 +118,7 @@ int32_t bad_usb_app(void* p) { | |||||||
|     FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); |     FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); | ||||||
|     furi_hal_usb_set_config(&usb_hid); |     furi_hal_usb_set_config(&usb_hid); | ||||||
| 
 | 
 | ||||||
|     BadUsbApp* bad_usb_app = bad_usb_app_alloc(); |     BadUsbApp* bad_usb_app = bad_usb_app_alloc((char*)p); | ||||||
| 
 | 
 | ||||||
|     view_dispatcher_run(bad_usb_app->view_dispatcher); |     view_dispatcher_run(bad_usb_app->view_dispatcher); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -144,7 +144,7 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c | |||||||
|         bad_usb->view, (BadUsbModel * model) { |         bad_usb->view, (BadUsbModel * model) { | ||||||
|             bad_usb->callback = callback; |             bad_usb->callback = callback; | ||||||
|             bad_usb->context = context; |             bad_usb->context = context; | ||||||
|             return false; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -153,7 +153,7 @@ void bad_usb_set_file_name(BadUsb* bad_usb, char* name) { | |||||||
|     with_view_model( |     with_view_model( | ||||||
|         bad_usb->view, (BadUsbModel * model) { |         bad_usb->view, (BadUsbModel * model) { | ||||||
|             model->file_name = name; |             model->file_name = name; | ||||||
|             return false; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -163,6 +163,6 @@ void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { | |||||||
|         bad_usb->view, (BadUsbModel * model) { |         bad_usb->view, (BadUsbModel * model) { | ||||||
|             memcpy(&(model->state), st, sizeof(BadUsbState)); |             memcpy(&(model->state), st, sizeof(BadUsbState)); | ||||||
|             model->anim_frame ^= 1; |             model->anim_frame ^= 1; | ||||||
|             return false; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -151,6 +151,6 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa | |||||||
|             model->rx_active = (model->rx_cnt != st->rx_cnt); |             model->rx_active = (model->rx_cnt != st->rx_cnt); | ||||||
|             model->tx_cnt = st->tx_cnt; |             model->tx_cnt = st->tx_cnt; | ||||||
|             model->rx_cnt = st->rx_cnt; |             model->rx_cnt = st->rx_cnt; | ||||||
|             return false; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -96,6 +96,6 @@ void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) { | |||||||
|     with_view_model( |     with_view_model( | ||||||
|         u2f->view, (U2fModel * model) { |         u2f->view, (U2fModel * model) { | ||||||
|             model->display_msg = msg; |             model->display_msg = msg; | ||||||
|             return false; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -40,6 +40,9 @@ const uint8_t *_I_125_10px[] = {_I_125_10px_0}; | |||||||
| const uint8_t _I_Nfc_10px_0[] = {0x00,0x80,0x00,0x00,0x01,0x22,0x02,0x43,0x02,0x45,0x02,0x49,0x02,0x31,0x02,0x22,0x02,0x00,0x01,0x80,0x00,}; | const uint8_t _I_Nfc_10px_0[] = {0x00,0x80,0x00,0x00,0x01,0x22,0x02,0x43,0x02,0x45,0x02,0x49,0x02,0x31,0x02,0x22,0x02,0x00,0x01,0x80,0x00,}; | ||||||
| const uint8_t *_I_Nfc_10px[] = {_I_Nfc_10px_0}; | const uint8_t *_I_Nfc_10px[] = {_I_Nfc_10px_0}; | ||||||
| 
 | 
 | ||||||
|  | const uint8_t _I_badusb_10px_0[] = {0x01,0x00,0x11,0x00,0x00,0x0f,0xe2,0x01,0xfc,0x80,0xdd,0x20,0x32,0x48,0x08,0x14,0x40,0x23,0xa8,0x08,0xa0,}; | ||||||
|  | const uint8_t *_I_badusb_10px[] = {_I_badusb_10px_0}; | ||||||
|  | 
 | ||||||
| const uint8_t _I_ble_10px_0[] = {0x00,0x04,0x00,0x8C,0x00,0x15,0x01,0x56,0x02,0x8C,0x02,0x8C,0x02,0x56,0x02,0x15,0x01,0x8C,0x00,0x04,0x00,}; | const uint8_t _I_ble_10px_0[] = {0x00,0x04,0x00,0x8C,0x00,0x15,0x01,0x56,0x02,0x8C,0x02,0x8C,0x02,0x56,0x02,0x15,0x01,0x8C,0x00,0x04,0x00,}; | ||||||
| const uint8_t *_I_ble_10px[] = {_I_ble_10px_0}; | const uint8_t *_I_ble_10px[] = {_I_ble_10px_0}; | ||||||
| 
 | 
 | ||||||
| @ -55,6 +58,9 @@ const uint8_t *_I_ir_10px[] = {_I_ir_10px_0}; | |||||||
| const uint8_t _I_sub1_10px_0[] = {0x01,0x00,0x12,0x00,0x81,0x40,0x69,0x30,0x2c,0x2c,0x0b,0x6a,0x01,0x28,0x0c,0x0a,0x65,0x01,0x98,0x40,0x00,0x26,}; | const uint8_t _I_sub1_10px_0[] = {0x01,0x00,0x12,0x00,0x81,0x40,0x69,0x30,0x2c,0x2c,0x0b,0x6a,0x01,0x28,0x0c,0x0a,0x65,0x01,0x98,0x40,0x00,0x26,}; | ||||||
| const uint8_t *_I_sub1_10px[] = {_I_sub1_10px_0}; | const uint8_t *_I_sub1_10px[] = {_I_sub1_10px_0}; | ||||||
| 
 | 
 | ||||||
|  | const uint8_t _I_u2f_10px_0[] = {0x00,0x00,0x00,0xFE,0x01,0x01,0x02,0x0C,0x00,0xF2,0x03,0x92,0x02,0x0C,0x00,0x01,0x02,0xFE,0x01,0x00,0x00,}; | ||||||
|  | const uint8_t *_I_u2f_10px[] = {_I_u2f_10px_0}; | ||||||
|  | 
 | ||||||
| const uint8_t _I_unknown_10px_0[] = {0x01,0x00,0x12,0x00,0xbc,0x40,0x39,0x90,0x0c,0x24,0x03,0x81,0x00,0xb0,0x40,0x26,0x00,0x12,0x00,0x08,0x14,0xc0,}; | const uint8_t _I_unknown_10px_0[] = {0x01,0x00,0x12,0x00,0xbc,0x40,0x39,0x90,0x0c,0x24,0x03,0x81,0x00,0xb0,0x40,0x26,0x00,0x12,0x00,0x08,0x14,0xc0,}; | ||||||
| const uint8_t *_I_unknown_10px[] = {_I_unknown_10px_0}; | const uint8_t *_I_unknown_10px[] = {_I_unknown_10px_0}; | ||||||
| 
 | 
 | ||||||
| @ -624,11 +630,13 @@ const Icon A_Levelup1_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rat | |||||||
| const Icon A_Levelup2_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rate=2,.frames=_A_Levelup2_128x64}; | const Icon A_Levelup2_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rate=2,.frames=_A_Levelup2_128x64}; | ||||||
| const Icon I_125_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_125_10px}; | const Icon I_125_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_125_10px}; | ||||||
| const Icon I_Nfc_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Nfc_10px}; | const Icon I_Nfc_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Nfc_10px}; | ||||||
|  | const Icon I_badusb_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_badusb_10px}; | ||||||
| const Icon I_ble_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ble_10px}; | const Icon I_ble_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ble_10px}; | ||||||
| const Icon I_dir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_dir_10px}; | const Icon I_dir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_dir_10px}; | ||||||
| const Icon I_ibutt_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ibutt_10px}; | const Icon I_ibutt_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ibutt_10px}; | ||||||
| const Icon I_ir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ir_10px}; | const Icon I_ir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ir_10px}; | ||||||
| const Icon I_sub1_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_sub1_10px}; | const Icon I_sub1_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_sub1_10px}; | ||||||
|  | const Icon I_u2f_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_u2f_10px}; | ||||||
| const Icon I_unknown_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_unknown_10px}; | const Icon I_unknown_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_unknown_10px}; | ||||||
| const Icon I_BLE_Pairing_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_BLE_Pairing_128x64}; | const Icon I_BLE_Pairing_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_BLE_Pairing_128x64}; | ||||||
| const Icon I_Ble_connected_38x34 = {.width=38,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_Ble_connected_38x34}; | const Icon I_Ble_connected_38x34 = {.width=38,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_Ble_connected_38x34}; | ||||||
|  | |||||||
| @ -7,11 +7,13 @@ extern const Icon A_Levelup1_128x64; | |||||||
| extern const Icon A_Levelup2_128x64; | extern const Icon A_Levelup2_128x64; | ||||||
| extern const Icon I_125_10px; | extern const Icon I_125_10px; | ||||||
| extern const Icon I_Nfc_10px; | extern const Icon I_Nfc_10px; | ||||||
|  | extern const Icon I_badusb_10px; | ||||||
| extern const Icon I_ble_10px; | extern const Icon I_ble_10px; | ||||||
| extern const Icon I_dir_10px; | extern const Icon I_dir_10px; | ||||||
| extern const Icon I_ibutt_10px; | extern const Icon I_ibutt_10px; | ||||||
| extern const Icon I_ir_10px; | extern const Icon I_ir_10px; | ||||||
| extern const Icon I_sub1_10px; | extern const Icon I_sub1_10px; | ||||||
|  | extern const Icon I_u2f_10px; | ||||||
| extern const Icon I_unknown_10px; | extern const Icon I_unknown_10px; | ||||||
| extern const Icon I_BLE_Pairing_128x64; | extern const Icon I_BLE_Pairing_128x64; | ||||||
| extern const Icon I_Ble_connected_38x34; | extern const Icon I_Ble_connected_38x34; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Archive/badusb_10px.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Archive/badusb_10px.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 576 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Archive/u2f_10px.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Archive/u2f_10px.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 583 B | 
| @ -116,6 +116,7 @@ void ble_glue_init() { | |||||||
| 
 | 
 | ||||||
| bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|  | 
 | ||||||
|     size_t countdown = 1000; |     size_t countdown = 1000; | ||||||
|     while(countdown > 0) { |     while(countdown > 0) { | ||||||
|         if(ble_glue->status == BleGlueStatusFusStarted) { |         if(ble_glue->status == BleGlueStatusFusStarted) { | ||||||
| @ -125,13 +126,14 @@ bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | |||||||
|         countdown--; |         countdown--; | ||||||
|         osDelay(1); |         osDelay(1); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     if(ble_glue->status == BleGlueStatusFusStarted) { |     if(ble_glue->status == BleGlueStatusFusStarted) { | ||||||
|         SHCI_GetWirelessFwInfo(info); |         SHCI_GetWirelessFwInfo(info); | ||||||
|     } else { |     } else { | ||||||
|         FURI_LOG_E(TAG, "Failed to start FUS"); |         FURI_LOG_E(TAG, "Failed to start FUS"); | ||||||
|         ble_glue->status = BleGlueStatusBroken; |         ble_glue->status = BleGlueStatusBroken; | ||||||
|     } |     } | ||||||
|     furi_hal_power_insomnia_exit(); | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -90,12 +90,14 @@ uint16_t furi_hal_power_insomnia_level() { | |||||||
| 
 | 
 | ||||||
| void furi_hal_power_insomnia_enter() { | void furi_hal_power_insomnia_enter() { | ||||||
|     vTaskSuspendAll(); |     vTaskSuspendAll(); | ||||||
|  |     furi_assert(furi_hal_power.insomnia < UINT8_MAX); | ||||||
|     furi_hal_power.insomnia++; |     furi_hal_power.insomnia++; | ||||||
|     xTaskResumeAll(); |     xTaskResumeAll(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_power_insomnia_exit() { | void furi_hal_power_insomnia_exit() { | ||||||
|     vTaskSuspendAll(); |     vTaskSuspendAll(); | ||||||
|  |     furi_assert(furi_hal_power.insomnia > 0); | ||||||
|     furi_hal_power.insomnia--; |     furi_hal_power.insomnia--; | ||||||
|     xTaskResumeAll(); |     xTaskResumeAll(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -116,6 +116,7 @@ void ble_glue_init() { | |||||||
| 
 | 
 | ||||||
| bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|  | 
 | ||||||
|     size_t countdown = 1000; |     size_t countdown = 1000; | ||||||
|     while(countdown > 0) { |     while(countdown > 0) { | ||||||
|         if(ble_glue->status == BleGlueStatusFusStarted) { |         if(ble_glue->status == BleGlueStatusFusStarted) { | ||||||
| @ -125,13 +126,14 @@ bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { | |||||||
|         countdown--; |         countdown--; | ||||||
|         osDelay(1); |         osDelay(1); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     if(ble_glue->status == BleGlueStatusFusStarted) { |     if(ble_glue->status == BleGlueStatusFusStarted) { | ||||||
|         SHCI_GetWirelessFwInfo(info); |         SHCI_GetWirelessFwInfo(info); | ||||||
|     } else { |     } else { | ||||||
|         FURI_LOG_E(TAG, "Failed to start FUS"); |         FURI_LOG_E(TAG, "Failed to start FUS"); | ||||||
|         ble_glue->status = BleGlueStatusBroken; |         ble_glue->status = BleGlueStatusBroken; | ||||||
|     } |     } | ||||||
|     furi_hal_power_insomnia_exit(); | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -90,12 +90,14 @@ uint16_t furi_hal_power_insomnia_level() { | |||||||
| 
 | 
 | ||||||
| void furi_hal_power_insomnia_enter() { | void furi_hal_power_insomnia_enter() { | ||||||
|     vTaskSuspendAll(); |     vTaskSuspendAll(); | ||||||
|  |     furi_assert(furi_hal_power.insomnia < UINT8_MAX); | ||||||
|     furi_hal_power.insomnia++; |     furi_hal_power.insomnia++; | ||||||
|     xTaskResumeAll(); |     xTaskResumeAll(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_power_insomnia_exit() { | void furi_hal_power_insomnia_exit() { | ||||||
|     vTaskSuspendAll(); |     vTaskSuspendAll(); | ||||||
|  |     furi_assert(furi_hal_power.insomnia > 0); | ||||||
|     furi_hal_power.insomnia--; |     furi_hal_power.insomnia--; | ||||||
|     xTaskResumeAll(); |     xTaskResumeAll(); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikolay Minaylov
						Nikolay Minaylov