Просмотр исходного кода

Merge Mass storage updates and fixes

from https://github.com/flipperdevices/flipperzero-good-faps
MX 2 лет назад
Родитель
Сommit
ce1383d0ea

+ 5 - 0
.catalog/CHANGELOG.md

@@ -1,3 +1,8 @@
+## v.1.2
+
+ * Fix deadlock on disk eject
+ * Locked USB notification
+
 ## v.1.1
 
  * Faster image creation

+ 1 - 1
application.fam

@@ -9,7 +9,7 @@ App(
     ],
     stack_size=2 * 1024,
     fap_description="Implements a mass storage device over USB for disk images",
-    fap_version="1.1",
+    fap_version="1.2",
     fap_icon="assets/mass_storage_10px.png",
     fap_icon_assets="assets",
     fap_category="USB",

BIN
assets/ActiveConnection_50x64.png


+ 0 - 1
helpers/mass_storage_usb.c

@@ -478,5 +478,4 @@ MassStorageUsb* mass_storage_usb_start(const char* filename, SCSIDeviceFunc fn)
 
 void mass_storage_usb_stop(MassStorageUsb* mass) {
     furi_hal_usb_set_config(mass->usb_prev, NULL);
-    // freed by usb_deinit asynchronously from usb thread
 }

+ 14 - 4
mass_storage_app.c

@@ -81,10 +81,18 @@ MassStorageApp* mass_storage_app_alloc(char* arg) {
         MassStorageAppViewStart,
         variable_item_list_get_view(app->variable_item_list));
 
+    app->widget = widget_alloc();
+    view_dispatcher_add_view(
+        app->view_dispatcher, MassStorageAppViewWidget, widget_get_view(app->widget));
+
     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
 
     if(storage_file_exists(app->fs_api, furi_string_get_cstr(app->file_path))) {
-        scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
+        if(!furi_hal_usb_is_locked()) {
+            scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
+        } else {
+            scene_manager_next_scene(app->scene_manager, MassStorageSceneUsbLocked);
+        }
     } else {
         scene_manager_next_scene(app->scene_manager, MassStorageSceneStart);
     }
@@ -100,11 +108,13 @@ void mass_storage_app_free(MassStorageApp* app) {
     view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewTextInput);
     view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewStart);
     view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewLoading);
+    view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewWidget);
 
     mass_storage_free(app->mass_storage_view);
     text_input_free(app->text_input);
     variable_item_list_free(app->variable_item_list);
     loading_free(app->loading);
+    widget_free(app->widget);
 
     // View dispatcher
     view_dispatcher_free(app->view_dispatcher);
@@ -113,9 +123,9 @@ void mass_storage_app_free(MassStorageApp* app) {
     furi_string_free(app->file_path);
 
     // Close records
-    furi_record_close("gui");
-    furi_record_close("storage");
-    furi_record_close("dialogs");
+    furi_record_close(RECORD_GUI);
+    furi_record_close(RECORD_STORAGE);
+    furi_record_close(RECORD_DIALOGS);
 
     free(app);
 }

+ 5 - 0
mass_storage_app_i.h

@@ -13,8 +13,10 @@
 #include <gui/modules/variable_item_list.h>
 #include <gui/modules/text_input.h>
 #include <gui/modules/loading.h>
+#include <gui/modules/widget.h>
 #include <storage/storage.h>
 #include "views/mass_storage_view.h"
+#include <mass_storage_icons.h>
 
 #define MASS_STORAGE_APP_PATH_FOLDER STORAGE_APP_DATA_PATH_PREFIX
 #define MASS_STORAGE_APP_EXTENSION ".img"
@@ -25,6 +27,7 @@ struct MassStorageApp {
     Storage* fs_api;
     ViewDispatcher* view_dispatcher;
     SceneManager* scene_manager;
+    Widget* widget;
     DialogsApp* dialogs;
     TextInput* text_input;
     VariableItemList* variable_item_list;
@@ -48,12 +51,14 @@ typedef enum {
     MassStorageAppViewTextInput,
     MassStorageAppViewWork,
     MassStorageAppViewLoading,
+    MassStorageAppViewWidget,
 } MassStorageAppView;
 
 enum MassStorageCustomEvent {
     // Reserve first 100 events for button types and indexes, starting from 0
     MassStorageCustomEventReserved = 100,
 
+    MassStorageCustomEventEject,
     MassStorageCustomEventFileSelect,
     MassStorageCustomEventNewImage,
     MassStorageCustomEventNameInput,

+ 1 - 0
scenes/mass_storage_scene_config.h

@@ -2,3 +2,4 @@ ADD_SCENE(mass_storage, start, Start)
 ADD_SCENE(mass_storage, file_select, FileSelect)
 ADD_SCENE(mass_storage, work, Work)
 ADD_SCENE(mass_storage, file_name, FileName)
+ADD_SCENE(mass_storage, usb_locked, UsbLocked)

+ 5 - 1
scenes/mass_storage_scene_file_name.c

@@ -66,7 +66,11 @@ bool mass_storage_scene_file_name_on_event(void* context, SceneManagerEvent even
                 MASS_STORAGE_APP_EXTENSION);
             if(mass_storage_create_image(
                    app->fs_api, furi_string_get_cstr(app->file_path), app->new_file_size)) {
-                scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
+                if(!furi_hal_usb_is_locked()) {
+                    scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
+                } else {
+                    scene_manager_next_scene(app->scene_manager, MassStorageSceneUsbLocked);
+                }
             } // TODO: error message screen
         }
     }

+ 5 - 2
scenes/mass_storage_scene_file_select.c

@@ -1,6 +1,5 @@
 #include "../mass_storage_app_i.h"
 #include "furi_hal_power.h"
-#include <mass_storage_icons.h>
 
 static bool mass_storage_file_select(MassStorageApp* mass_storage) {
     furi_assert(mass_storage);
@@ -21,7 +20,11 @@ void mass_storage_scene_file_select_on_enter(void* context) {
     MassStorageApp* mass_storage = context;
 
     if(mass_storage_file_select(mass_storage)) {
-        scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneWork);
+        if(!furi_hal_usb_is_locked()) {
+            scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneWork);
+        } else {
+            scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneUsbLocked);
+        }
     } else {
         scene_manager_previous_scene(mass_storage->scene_manager);
     }

+ 40 - 0
scenes/mass_storage_scene_usb_locked.c

@@ -0,0 +1,40 @@
+#include "../mass_storage_app_i.h"
+
+void mass_storage_scene_usb_locked_on_enter(void* context) {
+    MassStorageApp* app = context;
+
+    widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
+    widget_add_string_multiline_element(
+        app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
+    widget_add_string_multiline_element(
+        app->widget,
+        3,
+        30,
+        AlignLeft,
+        AlignTop,
+        FontSecondary,
+        "Disconnect from\nPC or phone to\nuse this function.");
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, MassStorageAppViewWidget);
+}
+
+bool mass_storage_scene_usb_locked_on_event(void* context, SceneManagerEvent event) {
+    MassStorageApp* app = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeBack) {
+        consumed = scene_manager_search_and_switch_to_previous_scene(
+            app->scene_manager, MassStorageSceneFileSelect);
+        if(!consumed) {
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                app->scene_manager, MassStorageSceneStart);
+        }
+    }
+
+    return consumed;
+}
+
+void mass_storage_scene_usb_locked_on_exit(void* context) {
+    MassStorageApp* app = context;
+    widget_reset(app->widget);
+}

+ 11 - 15
scenes/mass_storage_scene_work.c

@@ -48,27 +48,23 @@ static uint32_t file_num_blocks(void* ctx) {
 static void file_eject(void* ctx) {
     MassStorageApp* app = ctx;
     FURI_LOG_D(TAG, "EJECT");
-    furi_check(furi_mutex_acquire(app->usb_mutex, FuriWaitForever) == FuriStatusOk);
-    mass_storage_usb_stop(app->usb);
-    app->usb = NULL;
-    furi_check(furi_mutex_release(app->usb_mutex) == FuriStatusOk);
+    view_dispatcher_send_custom_event(app->view_dispatcher, MassStorageCustomEventEject);
 }
 
 bool mass_storage_scene_work_on_event(void* context, SceneManagerEvent event) {
     MassStorageApp* app = context;
     bool consumed = false;
-    if(event.type == SceneManagerEventTypeTick) {
-        // Update stats
-        mass_storage_set_stats(app->mass_storage_view, app->bytes_read, app->bytes_written);
-        // Handle eject
-        bool ejected;
-        furi_check(furi_mutex_acquire(app->usb_mutex, FuriWaitForever) == FuriStatusOk);
-        ejected = app->usb == NULL;
-        furi_check(furi_mutex_release(app->usb_mutex) == FuriStatusOk);
-        if(ejected) {
-            scene_manager_previous_scene(app->scene_manager);
-            consumed = true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == MassStorageCustomEventEject) {
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                app->scene_manager, MassStorageSceneFileSelect);
+            if(!consumed) {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    app->scene_manager, MassStorageSceneStart);
+            }
         }
+    } else if(event.type == SceneManagerEventTypeTick) {
+        mass_storage_set_stats(app->mass_storage_view, app->bytes_read, app->bytes_written);
     } else if(event.type == SceneManagerEventTypeBack) {
         consumed = scene_manager_search_and_switch_to_previous_scene(
             app->scene_manager, MassStorageSceneFileSelect);

+ 1 - 1
views/mass_storage_view.c

@@ -1,6 +1,6 @@
 #include "mass_storage_view.h"
+#include "../mass_storage_app_i.h"
 #include <gui/elements.h>
-#include <mass_storage_icons.h>
 
 struct MassStorage {
     View* view;