Skip to content

Commit 4b0ea1f

Browse files
authored
Mass storage: deadlock fix (#22)
1 parent 0a8fc7e commit 4b0ea1f

10 files changed

+82
-24
lines changed

assets/ActiveConnection_50x64.png

3.75 KB
Loading

helpers/mass_storage_usb.c

-1
Original file line numberDiff line numberDiff line change
@@ -478,5 +478,4 @@ MassStorageUsb* mass_storage_usb_start(const char* filename, SCSIDeviceFunc fn)
478478

479479
void mass_storage_usb_stop(MassStorageUsb* mass) {
480480
furi_hal_usb_set_config(mass->usb_prev, NULL);
481-
// freed by usb_deinit asynchronously from usb thread
482481
}

mass_storage_app.c

+14-4
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,18 @@ MassStorageApp* mass_storage_app_alloc(char* arg) {
8181
MassStorageAppViewStart,
8282
variable_item_list_get_view(app->variable_item_list));
8383

84+
app->widget = widget_alloc();
85+
view_dispatcher_add_view(
86+
app->view_dispatcher, MassStorageAppViewWidget, widget_get_view(app->widget));
87+
8488
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
8589

8690
if(storage_file_exists(app->fs_api, furi_string_get_cstr(app->file_path))) {
87-
scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
91+
if(!furi_hal_usb_is_locked()) {
92+
scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
93+
} else {
94+
scene_manager_next_scene(app->scene_manager, MassStorageSceneUsbLocked);
95+
}
8896
} else {
8997
scene_manager_next_scene(app->scene_manager, MassStorageSceneStart);
9098
}
@@ -100,11 +108,13 @@ void mass_storage_app_free(MassStorageApp* app) {
100108
view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewTextInput);
101109
view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewStart);
102110
view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewLoading);
111+
view_dispatcher_remove_view(app->view_dispatcher, MassStorageAppViewWidget);
103112

104113
mass_storage_free(app->mass_storage_view);
105114
text_input_free(app->text_input);
106115
variable_item_list_free(app->variable_item_list);
107116
loading_free(app->loading);
117+
widget_free(app->widget);
108118

109119
// View dispatcher
110120
view_dispatcher_free(app->view_dispatcher);
@@ -113,9 +123,9 @@ void mass_storage_app_free(MassStorageApp* app) {
113123
furi_string_free(app->file_path);
114124

115125
// Close records
116-
furi_record_close("gui");
117-
furi_record_close("storage");
118-
furi_record_close("dialogs");
126+
furi_record_close(RECORD_GUI);
127+
furi_record_close(RECORD_STORAGE);
128+
furi_record_close(RECORD_DIALOGS);
119129

120130
free(app);
121131
}

mass_storage_app_i.h

+5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
#include <gui/modules/variable_item_list.h>
1414
#include <gui/modules/text_input.h>
1515
#include <gui/modules/loading.h>
16+
#include <gui/modules/widget.h>
1617
#include <storage/storage.h>
1718
#include "views/mass_storage_view.h"
19+
#include <mass_storage_icons.h>
1820

1921
#define MASS_STORAGE_APP_PATH_FOLDER STORAGE_APP_DATA_PATH_PREFIX
2022
#define MASS_STORAGE_APP_EXTENSION ".img"
@@ -25,6 +27,7 @@ struct MassStorageApp {
2527
Storage* fs_api;
2628
ViewDispatcher* view_dispatcher;
2729
SceneManager* scene_manager;
30+
Widget* widget;
2831
DialogsApp* dialogs;
2932
TextInput* text_input;
3033
VariableItemList* variable_item_list;
@@ -48,12 +51,14 @@ typedef enum {
4851
MassStorageAppViewTextInput,
4952
MassStorageAppViewWork,
5053
MassStorageAppViewLoading,
54+
MassStorageAppViewWidget,
5155
} MassStorageAppView;
5256

5357
enum MassStorageCustomEvent {
5458
// Reserve first 100 events for button types and indexes, starting from 0
5559
MassStorageCustomEventReserved = 100,
5660

61+
MassStorageCustomEventEject,
5762
MassStorageCustomEventFileSelect,
5863
MassStorageCustomEventNewImage,
5964
MassStorageCustomEventNameInput,

scenes/mass_storage_scene_config.h

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ ADD_SCENE(mass_storage, start, Start)
22
ADD_SCENE(mass_storage, file_select, FileSelect)
33
ADD_SCENE(mass_storage, work, Work)
44
ADD_SCENE(mass_storage, file_name, FileName)
5+
ADD_SCENE(mass_storage, usb_locked, UsbLocked)

scenes/mass_storage_scene_file_name.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ bool mass_storage_scene_file_name_on_event(void* context, SceneManagerEvent even
6666
MASS_STORAGE_APP_EXTENSION);
6767
if(mass_storage_create_image(
6868
app->fs_api, furi_string_get_cstr(app->file_path), app->new_file_size)) {
69-
scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
69+
if(!furi_hal_usb_is_locked()) {
70+
scene_manager_next_scene(app->scene_manager, MassStorageSceneWork);
71+
} else {
72+
scene_manager_next_scene(app->scene_manager, MassStorageSceneUsbLocked);
73+
}
7074
} // TODO: error message screen
7175
}
7276
}

scenes/mass_storage_scene_file_select.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "../mass_storage_app_i.h"
22
#include "furi_hal_power.h"
3-
#include <mass_storage_icons.h>
43

54
static bool mass_storage_file_select(MassStorageApp* mass_storage) {
65
furi_assert(mass_storage);
@@ -21,7 +20,11 @@ void mass_storage_scene_file_select_on_enter(void* context) {
2120
MassStorageApp* mass_storage = context;
2221

2322
if(mass_storage_file_select(mass_storage)) {
24-
scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneWork);
23+
if(!furi_hal_usb_is_locked()) {
24+
scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneWork);
25+
} else {
26+
scene_manager_next_scene(mass_storage->scene_manager, MassStorageSceneUsbLocked);
27+
}
2528
} else {
2629
scene_manager_previous_scene(mass_storage->scene_manager);
2730
}
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "../mass_storage_app_i.h"
2+
3+
void mass_storage_scene_usb_locked_on_enter(void* context) {
4+
MassStorageApp* app = context;
5+
6+
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
7+
widget_add_string_multiline_element(
8+
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
9+
widget_add_string_multiline_element(
10+
app->widget,
11+
3,
12+
30,
13+
AlignLeft,
14+
AlignTop,
15+
FontSecondary,
16+
"Disconnect from\nPC or phone to\nuse this function.");
17+
18+
view_dispatcher_switch_to_view(app->view_dispatcher, MassStorageAppViewWidget);
19+
}
20+
21+
bool mass_storage_scene_usb_locked_on_event(void* context, SceneManagerEvent event) {
22+
MassStorageApp* app = context;
23+
bool consumed = false;
24+
25+
if(event.type == SceneManagerEventTypeBack) {
26+
consumed = scene_manager_search_and_switch_to_previous_scene(
27+
app->scene_manager, MassStorageSceneFileSelect);
28+
if(!consumed) {
29+
consumed = scene_manager_search_and_switch_to_previous_scene(
30+
app->scene_manager, MassStorageSceneStart);
31+
}
32+
}
33+
34+
return consumed;
35+
}
36+
37+
void mass_storage_scene_usb_locked_on_exit(void* context) {
38+
MassStorageApp* app = context;
39+
widget_reset(app->widget);
40+
}

scenes/mass_storage_scene_work.c

+11-15
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,23 @@ static uint32_t file_num_blocks(void* ctx) {
4848
static void file_eject(void* ctx) {
4949
MassStorageApp* app = ctx;
5050
FURI_LOG_D(TAG, "EJECT");
51-
furi_check(furi_mutex_acquire(app->usb_mutex, FuriWaitForever) == FuriStatusOk);
52-
mass_storage_usb_stop(app->usb);
53-
app->usb = NULL;
54-
furi_check(furi_mutex_release(app->usb_mutex) == FuriStatusOk);
51+
view_dispatcher_send_custom_event(app->view_dispatcher, MassStorageCustomEventEject);
5552
}
5653

5754
bool mass_storage_scene_work_on_event(void* context, SceneManagerEvent event) {
5855
MassStorageApp* app = context;
5956
bool consumed = false;
60-
if(event.type == SceneManagerEventTypeTick) {
61-
// Update stats
62-
mass_storage_set_stats(app->mass_storage_view, app->bytes_read, app->bytes_written);
63-
// Handle eject
64-
bool ejected;
65-
furi_check(furi_mutex_acquire(app->usb_mutex, FuriWaitForever) == FuriStatusOk);
66-
ejected = app->usb == NULL;
67-
furi_check(furi_mutex_release(app->usb_mutex) == FuriStatusOk);
68-
if(ejected) {
69-
scene_manager_previous_scene(app->scene_manager);
70-
consumed = true;
57+
if(event.type == SceneManagerEventTypeCustom) {
58+
if(event.event == MassStorageCustomEventEject) {
59+
consumed = scene_manager_search_and_switch_to_previous_scene(
60+
app->scene_manager, MassStorageSceneFileSelect);
61+
if(!consumed) {
62+
consumed = scene_manager_search_and_switch_to_previous_scene(
63+
app->scene_manager, MassStorageSceneStart);
64+
}
7165
}
66+
} else if(event.type == SceneManagerEventTypeTick) {
67+
mass_storage_set_stats(app->mass_storage_view, app->bytes_read, app->bytes_written);
7268
} else if(event.type == SceneManagerEventTypeBack) {
7369
consumed = scene_manager_search_and_switch_to_previous_scene(
7470
app->scene_manager, MassStorageSceneFileSelect);

views/mass_storage_view.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "mass_storage_view.h"
2+
#include "../mass_storage_app_i.h"
23
#include <gui/elements.h>
3-
#include <mass_storage_icons.h>
44

55
struct MassStorage {
66
View* view;

0 commit comments

Comments
 (0)