Skip to content

Commit

Permalink
Mass storage: deadlock fix (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
nminaylov committed Aug 15, 2023
1 parent b108d7a commit 19cc230
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 24 deletions.
Binary file added mass_storage/assets/ActiveConnection_50x64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion mass_storage/helpers/mass_storage_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
18 changes: 14 additions & 4 deletions mass_storage/mass_storage_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down
5 changes: 5 additions & 0 deletions mass_storage/mass_storage_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions mass_storage/scenes/mass_storage_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
6 changes: 5 additions & 1 deletion mass_storage/scenes/mass_storage_scene_file_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
7 changes: 5 additions & 2 deletions mass_storage/scenes/mass_storage_scene_file_select.c
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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);
}
Expand Down
40 changes: 40 additions & 0 deletions mass_storage/scenes/mass_storage_scene_usb_locked.c
Original file line number Diff line number Diff line change
@@ -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);
}
26 changes: 11 additions & 15 deletions mass_storage/scenes/mass_storage_scene_work.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion mass_storage/views/mass_storage_view.c
Original file line number Diff line number Diff line change
@@ -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;
Expand Down

0 comments on commit 19cc230

Please sign in to comment.