[FL-2432], [FL-2487] Rework bt keys load and save (#1139)
* bt keys: rework load and save with saved_struct * bt: rename bt keys storage functions * furi_hal_nfc: allow context switch during emilation * bt settings: rework with saved struct * infrared: replace file worker with dialogs and storage * Core, Loader: fix thread allocation tracking, much better, so wow. Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
df66f4f6ba
commit
7c692a9f36
@ -320,7 +320,7 @@ int32_t bt_srv() {
|
|||||||
Bt* bt = bt_alloc();
|
Bt* bt = bt_alloc();
|
||||||
|
|
||||||
// Read keys
|
// Read keys
|
||||||
if(!bt_load_key_storage(bt)) {
|
if(!bt_keys_storage_load(bt)) {
|
||||||
FURI_LOG_W(TAG, "Failed to load bonding keys");
|
FURI_LOG_W(TAG, "Failed to load bonding keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,11 +365,11 @@ int32_t bt_srv() {
|
|||||||
// Display PIN code
|
// Display PIN code
|
||||||
bt_pin_code_show(bt, message.data.pin_code);
|
bt_pin_code_show(bt, message.data.pin_code);
|
||||||
} else if(message.type == BtMessageTypeKeysStorageUpdated) {
|
} else if(message.type == BtMessageTypeKeysStorageUpdated) {
|
||||||
bt_save_key_storage(bt);
|
bt_keys_storage_save(bt);
|
||||||
} else if(message.type == BtMessageTypeSetProfile) {
|
} else if(message.type == BtMessageTypeSetProfile) {
|
||||||
bt_change_profile(bt, &message);
|
bt_change_profile(bt, &message);
|
||||||
} else if(message.type == BtMessageTypeForgetBondedDevices) {
|
} else if(message.type == BtMessageTypeForgetBondedDevices) {
|
||||||
bt_delete_key_storage(bt);
|
bt_keys_storage_delete(bt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,46 +1,47 @@
|
|||||||
#include "bt_keys_storage.h"
|
#include "bt_keys_storage.h"
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <file_worker.h>
|
#include <lib/toolbox/saved_struct.h>
|
||||||
|
|
||||||
#define BT_KEYS_STORAGE_TAG "bt keys storage"
|
|
||||||
#define BT_KEYS_STORAGE_PATH "/int/bt.keys"
|
#define BT_KEYS_STORAGE_PATH "/int/bt.keys"
|
||||||
|
#define BT_KEYS_STORAGE_VERSION (0)
|
||||||
|
#define BT_KEYS_STORAGE_MAGIC (0x18)
|
||||||
|
|
||||||
bool bt_load_key_storage(Bt* bt) {
|
bool bt_keys_storage_load(Bt* bt) {
|
||||||
furi_assert(bt);
|
furi_assert(bt);
|
||||||
|
|
||||||
bool file_loaded = false;
|
bool file_loaded = false;
|
||||||
furi_hal_bt_get_key_storage_buff(&bt->bt_keys_addr_start, &bt->bt_keys_size);
|
|
||||||
|
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
furi_hal_bt_get_key_storage_buff(&bt->bt_keys_addr_start, &bt->bt_keys_size);
|
||||||
if(file_worker_open(file_worker, BT_KEYS_STORAGE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
|
||||||
furi_hal_bt_nvm_sram_sem_acquire();
|
furi_hal_bt_nvm_sram_sem_acquire();
|
||||||
if(file_worker_read(file_worker, bt->bt_keys_addr_start, bt->bt_keys_size)) {
|
file_loaded = saved_struct_load(
|
||||||
file_loaded = true;
|
BT_KEYS_STORAGE_PATH,
|
||||||
}
|
bt->bt_keys_addr_start,
|
||||||
|
bt->bt_keys_size,
|
||||||
|
BT_KEYS_STORAGE_MAGIC,
|
||||||
|
BT_KEYS_STORAGE_VERSION);
|
||||||
furi_hal_bt_nvm_sram_sem_release();
|
furi_hal_bt_nvm_sram_sem_release();
|
||||||
}
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
return file_loaded;
|
return file_loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_save_key_storage(Bt* bt) {
|
bool bt_keys_storage_save(Bt* bt) {
|
||||||
furi_assert(bt);
|
furi_assert(bt);
|
||||||
furi_assert(bt->bt_keys_addr_start);
|
furi_assert(bt->bt_keys_addr_start);
|
||||||
|
|
||||||
bool file_saved = false;
|
bool file_saved = false;
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
|
||||||
if(file_worker_open(file_worker, BT_KEYS_STORAGE_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
|
|
||||||
furi_hal_bt_nvm_sram_sem_acquire();
|
furi_hal_bt_nvm_sram_sem_acquire();
|
||||||
if(file_worker_write(file_worker, bt->bt_keys_addr_start, bt->bt_keys_size)) {
|
file_saved = saved_struct_save(
|
||||||
file_saved = true;
|
BT_KEYS_STORAGE_PATH,
|
||||||
}
|
bt->bt_keys_addr_start,
|
||||||
|
bt->bt_keys_size,
|
||||||
|
BT_KEYS_STORAGE_MAGIC,
|
||||||
|
BT_KEYS_STORAGE_VERSION);
|
||||||
furi_hal_bt_nvm_sram_sem_release();
|
furi_hal_bt_nvm_sram_sem_release();
|
||||||
}
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
return file_saved;
|
return file_saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_delete_key_storage(Bt* bt) {
|
bool bt_keys_storage_delete(Bt* bt) {
|
||||||
furi_assert(bt);
|
furi_assert(bt);
|
||||||
bool delete_succeed = false;
|
bool delete_succeed = false;
|
||||||
bool bt_is_active = furi_hal_bt_is_active();
|
bool bt_is_active = furi_hal_bt_is_active();
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "bt_i.h"
|
#include "bt_i.h"
|
||||||
|
|
||||||
bool bt_load_key_storage(Bt* bt);
|
bool bt_keys_storage_load(Bt* bt);
|
||||||
|
|
||||||
bool bt_save_key_storage(Bt* bt);
|
bool bt_keys_storage_save(Bt* bt);
|
||||||
|
|
||||||
bool bt_delete_key_storage(Bt* bt);
|
bool bt_keys_storage_delete(Bt* bt);
|
||||||
|
@ -1,50 +1,22 @@
|
|||||||
#include "bt_settings.h"
|
#include "bt_settings.h"
|
||||||
#include <furi.h>
|
|
||||||
#include <file_worker.h>
|
|
||||||
|
|
||||||
#define TAG "BtSettings"
|
#include <furi.h>
|
||||||
|
#include <lib/toolbox/saved_struct.h>
|
||||||
|
|
||||||
#define BT_SETTINGS_PATH "/int/bt.settings"
|
#define BT_SETTINGS_PATH "/int/bt.settings"
|
||||||
|
#define BT_SETTINGS_VERSION (0)
|
||||||
|
#define BT_SETTINGS_MAGIC (0x19)
|
||||||
|
|
||||||
bool bt_settings_load(BtSettings* bt_settings) {
|
bool bt_settings_load(BtSettings* bt_settings) {
|
||||||
furi_assert(bt_settings);
|
furi_assert(bt_settings);
|
||||||
bool file_loaded = false;
|
|
||||||
BtSettings settings = {};
|
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH);
|
return saved_struct_load(
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION);
|
||||||
if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
|
||||||
if(file_worker_read(file_worker, &settings, sizeof(settings))) {
|
|
||||||
file_loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
|
|
||||||
if(file_loaded) {
|
|
||||||
FURI_LOG_I(TAG, "Settings load success");
|
|
||||||
if(settings.version != BT_SETTINGS_VERSION) {
|
|
||||||
FURI_LOG_E(TAG, "Settings version mismatch");
|
|
||||||
} else {
|
|
||||||
osKernelLock();
|
|
||||||
*bt_settings = settings;
|
|
||||||
osKernelUnlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FURI_LOG_E(TAG, "Settings load failed");
|
|
||||||
}
|
|
||||||
return file_loaded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_settings_save(BtSettings* bt_settings) {
|
bool bt_settings_save(BtSettings* bt_settings) {
|
||||||
furi_assert(bt_settings);
|
furi_assert(bt_settings);
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
FileWorker* file_worker = file_worker_alloc(true);
|
return saved_struct_save(
|
||||||
if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
|
BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION);
|
||||||
if(file_worker_write(file_worker, bt_settings, sizeof(BtSettings))) {
|
|
||||||
FURI_LOG_I(TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_worker_free(file_worker);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define BT_SETTINGS_VERSION (0)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t version;
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
} BtSettings;
|
} BtSettings;
|
||||||
|
|
||||||
|
@ -49,12 +49,14 @@ int32_t InfraredApp::run(void* args) {
|
|||||||
InfraredApp::InfraredApp() {
|
InfraredApp::InfraredApp() {
|
||||||
furi_check(InfraredAppRemoteManager::max_button_name_length < get_text_store_size());
|
furi_check(InfraredAppRemoteManager::max_button_name_length < get_text_store_size());
|
||||||
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
||||||
|
dialogs = static_cast<DialogsApp*>(furi_record_open("dialogs"));
|
||||||
infrared_worker = infrared_worker_alloc();
|
infrared_worker = infrared_worker_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
InfraredApp::~InfraredApp() {
|
InfraredApp::~InfraredApp() {
|
||||||
infrared_worker_free(infrared_worker);
|
infrared_worker_free(infrared_worker);
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
|
furi_record_close("dialogs");
|
||||||
for(auto& [key, scene] : scenes) delete scene;
|
for(auto& [key, scene] : scenes) delete scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +250,10 @@ void InfraredApp::notify_blink_green() {
|
|||||||
notification_message(notification, &sequence);
|
notification_message(notification, &sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DialogsApp* InfraredApp::get_dialogs() {
|
||||||
|
return dialogs;
|
||||||
|
}
|
||||||
|
|
||||||
void InfraredApp::notify_green_on() {
|
void InfraredApp::notify_green_on() {
|
||||||
notification_message(notification, &sequence_set_only_green_255);
|
notification_message(notification, &sequence_set_only_green_255);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
#include <infrared_worker.h>
|
#include <infrared_worker.h>
|
||||||
|
|
||||||
#include "scene/infrared_app_scene.h"
|
#include "scene/infrared_app_scene.h"
|
||||||
@ -228,6 +229,9 @@ public:
|
|||||||
/** Blink green light */
|
/** Blink green light */
|
||||||
void notify_blink_green();
|
void notify_blink_green();
|
||||||
|
|
||||||
|
/** Get Dialogs instance */
|
||||||
|
DialogsApp* get_dialogs();
|
||||||
|
|
||||||
/** Text input callback
|
/** Text input callback
|
||||||
*
|
*
|
||||||
* @param context - context to pass to callback
|
* @param context - context to pass to callback
|
||||||
@ -286,6 +290,8 @@ private:
|
|||||||
|
|
||||||
/** Notification instance */
|
/** Notification instance */
|
||||||
NotificationApp* notification;
|
NotificationApp* notification;
|
||||||
|
/** Dialogs instance */
|
||||||
|
DialogsApp* dialogs;
|
||||||
/** View manager instance */
|
/** View manager instance */
|
||||||
InfraredAppViewManager view_manager;
|
InfraredAppViewManager view_manager;
|
||||||
/** Remote manager instance */
|
/** Remote manager instance */
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <file_worker_cpp.h>
|
|
||||||
|
|
||||||
void InfraredAppBruteForce::add_record(int index, const char* name) {
|
void InfraredAppBruteForce::add_record(int index, const char* name) {
|
||||||
records[name].index = index;
|
records[name].index = index;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include <file_worker_cpp.h>
|
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
#include "infrared_app_remote_manager.h"
|
#include "infrared_app_remote_manager.h"
|
||||||
#include "infrared/helpers/infrared_parser.h"
|
#include "infrared/helpers/infrared_parser.h"
|
||||||
@ -22,26 +21,34 @@ std::string InfraredAppRemoteManager::make_full_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string& name) {
|
std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string& name) {
|
||||||
bool exist = true;
|
std::string result_name;
|
||||||
FileWorkerCpp file_worker;
|
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
|
||||||
|
|
||||||
if(!file_worker.is_file_exist(
|
FS_Error error = storage_common_stat(
|
||||||
make_full_name(InfraredApp::infrared_directory, name).c_str(), &exist)) {
|
storage, make_full_name(InfraredApp::infrared_directory, name).c_str(), NULL);
|
||||||
return std::string();
|
|
||||||
} else if(!exist) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if(error == FSE_NOT_EXIST) {
|
||||||
|
result_name = name;
|
||||||
|
} else if(error != FSE_OK) {
|
||||||
|
result_name = std::string();
|
||||||
|
} else {
|
||||||
/* if suggested name is occupied, try another one (name2, name3, etc) */
|
/* if suggested name is occupied, try another one (name2, name3, etc) */
|
||||||
uint32_t i = 1;
|
uint32_t i = 1;
|
||||||
bool file_worker_result = false;
|
|
||||||
std::string new_name;
|
std::string new_name;
|
||||||
do {
|
do {
|
||||||
new_name = make_full_name(InfraredApp::infrared_directory, name + std::to_string(++i));
|
new_name = make_full_name(InfraredApp::infrared_directory, name + std::to_string(++i));
|
||||||
file_worker_result = file_worker.is_file_exist(new_name.c_str(), &exist);
|
error = storage_common_stat(storage, new_name.c_str(), NULL);
|
||||||
} while(file_worker_result && exist);
|
} while(error == FSE_OK);
|
||||||
|
|
||||||
return !exist ? name + std::to_string(i) : std::string();
|
if(error == FSE_NOT_EXIST) {
|
||||||
|
result_name = name + std::to_string(i);
|
||||||
|
} else {
|
||||||
|
result_name = std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_record_close("storage");
|
||||||
|
return result_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfraredAppRemoteManager::add_button(const char* button_name, const InfraredAppSignal& signal) {
|
bool InfraredAppRemoteManager::add_button(const char* button_name, const InfraredAppSignal& signal) {
|
||||||
@ -84,12 +91,14 @@ const InfraredAppSignal& InfraredAppRemoteManager::get_button_data(size_t index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InfraredAppRemoteManager::delete_remote() {
|
bool InfraredAppRemoteManager::delete_remote() {
|
||||||
bool result;
|
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
|
||||||
FileWorkerCpp file_worker;
|
|
||||||
result = file_worker.remove(make_full_name(remote->path, remote->name).c_str());
|
|
||||||
|
|
||||||
|
FS_Error error =
|
||||||
|
storage_common_remove(storage, make_full_name(remote->path, remote->name).c_str());
|
||||||
reset_remote();
|
reset_remote();
|
||||||
return result;
|
|
||||||
|
furi_record_close("storage");
|
||||||
|
return (error == FSE_OK || error == FSE_NOT_EXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfraredAppRemoteManager::reset_remote() {
|
void InfraredAppRemoteManager::reset_remote() {
|
||||||
@ -129,14 +138,15 @@ bool InfraredAppRemoteManager::rename_remote(const char* str) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileWorkerCpp file_worker;
|
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
|
||||||
|
|
||||||
std::string old_filename = make_full_name(remote->path, remote->name);
|
std::string old_filename = make_full_name(remote->path, remote->name);
|
||||||
std::string new_filename = make_full_name(remote->path, new_name);
|
std::string new_filename = make_full_name(remote->path, new_name);
|
||||||
bool result = file_worker.rename(old_filename.c_str(), new_filename.c_str());
|
FS_Error error = storage_common_rename(storage, old_filename.c_str(), new_filename.c_str());
|
||||||
|
|
||||||
remote->name = new_name;
|
remote->name = new_name;
|
||||||
|
|
||||||
return result;
|
furi_record_close("storage");
|
||||||
|
return (error == FSE_OK || error == FSE_EXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfraredAppRemoteManager::rename_button(uint32_t index, const char* str) {
|
bool InfraredAppRemoteManager::rename_button(uint32_t index, const char* str) {
|
||||||
@ -155,11 +165,10 @@ size_t InfraredAppRemoteManager::get_number_of_buttons() {
|
|||||||
|
|
||||||
bool InfraredAppRemoteManager::store(void) {
|
bool InfraredAppRemoteManager::store(void) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
FileWorkerCpp file_worker;
|
|
||||||
|
|
||||||
if(!file_worker.mkdir(InfraredApp::infrared_directory)) return false;
|
|
||||||
|
|
||||||
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
|
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
|
||||||
|
|
||||||
|
if(!storage_simply_mkdir(storage, InfraredApp::infrared_directory)) return false;
|
||||||
|
|
||||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||||
|
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <gui/modules/dialog_ex.h>
|
#include <gui/modules/dialog_ex.h>
|
||||||
#include <file_worker_cpp.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
@ -88,13 +87,8 @@ bool InfraredAppSceneLearnSuccess::on_event(InfraredApp* app, InfraredAppEvent*
|
|||||||
break;
|
break;
|
||||||
case DialogExResultRight: {
|
case DialogExResultRight: {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
FileWorkerCpp file_worker;
|
|
||||||
if(!button_pressed) {
|
if(!button_pressed) {
|
||||||
if(file_worker.check_errors()) {
|
|
||||||
app->switch_to_next_scene(InfraredApp::Scene::LearnEnterName);
|
app->switch_to_next_scene(InfraredApp::Scene::LearnEnterName);
|
||||||
} else {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
#include "../infrared_app.h"
|
#include "../infrared_app.h"
|
||||||
#include "infrared/infrared_app_event.h"
|
#include "infrared/infrared_app_event.h"
|
||||||
#include <text_store.h>
|
#include <text_store.h>
|
||||||
#include <file_worker_cpp.h>
|
|
||||||
|
|
||||||
void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
|
void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
|
||||||
furi_assert(app);
|
furi_assert(app);
|
||||||
|
|
||||||
FileWorkerCpp file_worker;
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool file_select_result;
|
bool file_select_result;
|
||||||
auto remote_manager = app->get_remote_manager();
|
auto remote_manager = app->get_remote_manager();
|
||||||
@ -15,13 +13,15 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
|
|||||||
last_selected_remote.size() ? last_selected_remote.c_str() : nullptr;
|
last_selected_remote.size() ? last_selected_remote.c_str() : nullptr;
|
||||||
auto filename_ts =
|
auto filename_ts =
|
||||||
std::make_unique<TextStore>(InfraredAppRemoteManager::max_remote_name_length);
|
std::make_unique<TextStore>(InfraredAppRemoteManager::max_remote_name_length);
|
||||||
|
DialogsApp* dialogs = app->get_dialogs();
|
||||||
|
|
||||||
InfraredAppViewManager* view_manager = app->get_view_manager();
|
InfraredAppViewManager* view_manager = app->get_view_manager();
|
||||||
ButtonMenu* button_menu = view_manager->get_button_menu();
|
ButtonMenu* button_menu = view_manager->get_button_menu();
|
||||||
button_menu_reset(button_menu);
|
button_menu_reset(button_menu);
|
||||||
view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu);
|
view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu);
|
||||||
|
|
||||||
file_select_result = file_worker.file_select(
|
file_select_result = dialog_file_select_show(
|
||||||
|
dialogs,
|
||||||
InfraredApp::infrared_directory,
|
InfraredApp::infrared_directory,
|
||||||
InfraredApp::infrared_extension,
|
InfraredApp::infrared_extension,
|
||||||
filename_ts->text,
|
filename_ts->text,
|
||||||
|
@ -239,26 +239,11 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
|||||||
event.type = LoaderEventTypeApplicationStarted;
|
event.type = LoaderEventTypeApplicationStarted;
|
||||||
furi_pubsub_publish(loader_instance->pubsub, &event);
|
furi_pubsub_publish(loader_instance->pubsub, &event);
|
||||||
furi_hal_power_insomnia_enter();
|
furi_hal_power_insomnia_enter();
|
||||||
|
|
||||||
// Snapshot current memory usage
|
|
||||||
instance->free_heap_size = memmgr_get_free_heap();
|
|
||||||
} else if(thread_state == FuriThreadStateStopped) {
|
} else if(thread_state == FuriThreadStateStopped) {
|
||||||
/*
|
|
||||||
* Current Leak Sanitizer assumes that memory is allocated and freed
|
|
||||||
* inside one thread. Timers are allocated in one task, but freed in
|
|
||||||
* Timer-Task thread, and xTimerDelete() just put command to queue.
|
|
||||||
* To avoid some bad cases there are few fixes:
|
|
||||||
* 1) delay for Timer to process commands
|
|
||||||
* 2) there are 'heap diff' which shows difference in heap before task
|
|
||||||
* started and after task completed. In process of leakage monitoring
|
|
||||||
* both values should be taken into account.
|
|
||||||
*/
|
|
||||||
furi_hal_delay_ms(20);
|
|
||||||
int heap_diff = instance->free_heap_size - memmgr_get_free_heap();
|
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
"Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.",
|
"Application thread stopped. Free heap: %d. Thread allocation balance: %d.",
|
||||||
heap_diff,
|
memmgr_get_free_heap(),
|
||||||
furi_thread_get_heap_size(instance->application_thread));
|
furi_thread_get_heap_size(instance->application_thread));
|
||||||
|
|
||||||
if(loader_instance->application_arguments) {
|
if(loader_instance->application_arguments) {
|
||||||
|
@ -30,7 +30,6 @@ struct Loader {
|
|||||||
Submenu* debug_menu;
|
Submenu* debug_menu;
|
||||||
Submenu* settings_menu;
|
Submenu* settings_menu;
|
||||||
|
|
||||||
size_t free_heap_size;
|
|
||||||
volatile uint8_t lock_count;
|
volatile uint8_t lock_count;
|
||||||
|
|
||||||
FuriPubSub* pubsub;
|
FuriPubSub* pubsub;
|
||||||
|
@ -171,9 +171,18 @@ size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) {
|
|||||||
!MemmgrHeapAllocDict_end_p(alloc_dict_it);
|
!MemmgrHeapAllocDict_end_p(alloc_dict_it);
|
||||||
MemmgrHeapAllocDict_next(alloc_dict_it)) {
|
MemmgrHeapAllocDict_next(alloc_dict_it)) {
|
||||||
MemmgrHeapAllocDict_itref_t* data = MemmgrHeapAllocDict_ref(alloc_dict_it);
|
MemmgrHeapAllocDict_itref_t* data = MemmgrHeapAllocDict_ref(alloc_dict_it);
|
||||||
|
if(data->key != 0) {
|
||||||
|
uint8_t* puc = (uint8_t*)data->key;
|
||||||
|
puc -= xHeapStructSize;
|
||||||
|
BlockLink_t* pxLink = (void*)puc;
|
||||||
|
|
||||||
|
if((pxLink->xBlockSize & xBlockAllocatedBit) != 0 &&
|
||||||
|
pxLink->pxNextFreeBlock == NULL) {
|
||||||
leftovers += data->value;
|
leftovers += data->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
memmgr_heap_thread_trace_depth--;
|
memmgr_heap_thread_trace_depth--;
|
||||||
}
|
}
|
||||||
(void)xTaskResumeAll();
|
(void)xTaskResumeAll();
|
||||||
|
@ -45,6 +45,7 @@ static void furi_thread_body(void* context) {
|
|||||||
thread->ret = thread->callback(thread->context);
|
thread->ret = thread->callback(thread->context);
|
||||||
|
|
||||||
if(thread->heap_trace_enabled == true) {
|
if(thread->heap_trace_enabled == true) {
|
||||||
|
osDelay(33);
|
||||||
thread->heap_size = memmgr_heap_get_thread_memory(thread_id);
|
thread->heap_size = memmgr_heap_get_thread_memory(thread_id);
|
||||||
memmgr_heap_disable_thread_trace(thread_id);
|
memmgr_heap_disable_thread_trace(thread_id);
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ bool furi_hal_nfc_listen(
|
|||||||
rfalNfcDeactivate(true);
|
rfalNfcDeactivate(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
osThreadYield();
|
osDelay(1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -498,7 +498,7 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
|
|||||||
} else {
|
} else {
|
||||||
start = DWT->CYCCNT;
|
start = DWT->CYCCNT;
|
||||||
}
|
}
|
||||||
osThreadYield();
|
osDelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) {
|
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) {
|
||||||
|
Loading…
Reference in New Issue
Block a user