mirror of
https://protopirate.net/ProtoPirate/ProtoPirate.git
synced 2026-10-22 19:01:14 +00:00
Merge pull request 'Add ENABLE_MODELS_DATABASE build flag' (#67) from RalphWiggum/ProtoPirate:models_build_flag into main
FAP Build / ufbt: Build for Momentum dev (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum release (push) Canceled after 0s
FAP Build / ufbt: Build for OFW dev channel (push) Canceled after 0s
FAP Build / ufbt: Build for OFW release channel (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed dev (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed release (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum dev (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum release (push) Canceled after 0s
FAP Build / ufbt: Build for OFW dev channel (push) Canceled after 0s
FAP Build / ufbt: Build for OFW release channel (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed dev (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed release (push) Canceled after 0s
Reviewed-on: http://protopirate.net/ProtoPirate/ProtoPirate/pulls/67 Reviewed-by: MMX <mmx@no-reply.protopirate.net>
This commit is contained in:
commit
1c26a60cf3
48 files changed
+688
-587
No files matched your search
+8
-1
@@ -14,6 +14,7 @@ def ProtoPirateDefineEnabled(name, app_manifest_path=app_manifest_path):
|
||||
|
||||
_ENABLE_TIMING_TUNER = ProtoPirateDefineEnabled("ENABLE_TIMING_TUNER_SCENE")
|
||||
_ENABLE_EMULATE = ProtoPirateDefineEnabled("ENABLE_EMULATE_FEATURE")
|
||||
_ENABLE_MODELS_DATABASE = ProtoPirateDefineEnabled("ENABLE_MODELS_DATABASE")
|
||||
|
||||
_MAIN_APP_SOURCES = [
|
||||
"*.c*",
|
||||
@@ -43,6 +44,12 @@ if not _ENABLE_EMULATE:
|
||||
"!protopirate_scene_emulate.c",
|
||||
]
|
||||
|
||||
|
||||
if _ENABLE_MODELS_DATABASE:
|
||||
_ASSETS="assets"
|
||||
else:
|
||||
_ASSETS="assets/keystore"
|
||||
|
||||
App(
|
||||
appid="proto_pirate",
|
||||
name="ProtoPirate",
|
||||
@@ -56,7 +63,7 @@ App(
|
||||
fap_icon="images/protopirate_10px.png",
|
||||
fap_category="Sub-GHz",
|
||||
fap_icon_assets="images",
|
||||
fap_file_assets="keystore",
|
||||
fap_file_assets=_ASSETS,
|
||||
cdefines=["PROTOPIRATE_PROTOCOL_RX_ONLY=1"],
|
||||
sources=_MAIN_APP_SOURCES,
|
||||
)
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
|
||||
// #define ENABLE_TIMING_TUNER_SCENE
|
||||
#define ENABLE_SUB_DECODE_SCENE
|
||||
#define ENABLE_EMULATE_FEATURE
|
||||
#define ENABLE_MODELS_DATABASE
|
||||
|
||||
#if defined(ENABLE_EMULATE_FEATURE) && !defined(PROTOPIRATE_PROTOCOL_RX_ONLY)
|
||||
#define PROTOPIRATE_WITH_ENCODER 1
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "protopirate_models.h"
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
|
||||
#define TAG "PPModels"
|
||||
|
||||
#define PROTOPIRATE_MODELS_FILE APP_ASSETS_PATH("models.txt")
|
||||
#define PROTOPIRATE_MODELS_FILE APP_ASSETS_PATH("models_db/models.txt")
|
||||
|
||||
//Models File Format.
|
||||
#define MODELS_FILE_HEADER "ProtoPirate Car Models Database"
|
||||
@@ -294,3 +295,4 @@ uint16_t car_model_get_count(void) {
|
||||
//Finished, return the count or 0 if error.
|
||||
return (uint16_t)model_count;
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include "../defines.h"
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
#include <lib/subghz/types.h>
|
||||
#include "core/record.h"
|
||||
#include <lib/subghz/subghz_setting.h>
|
||||
@@ -18,3 +21,4 @@ bool car_model_get_by_index(
|
||||
SubGhzSetting* app_settings);
|
||||
|
||||
uint16_t car_model_get_count(void);
|
||||
#endif
|
||||
@@ -0,0 +1,258 @@
|
||||
#include "protopirate_plugins.h"
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
|
||||
#define TAG "PPPlugins"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Plugin load / unload
|
||||
// -----------------------------------------------------------------------------
|
||||
const FlipperAppPluginDescriptor* load_plugin_fal(
|
||||
FlipperApplication** fal_app,
|
||||
const char* plugin_path,
|
||||
const char* application_id,
|
||||
uint32_t api_version) {
|
||||
const FlipperAppPluginDescriptor* app_descriptor;
|
||||
|
||||
bool return_value = false;
|
||||
do {
|
||||
FlipperApplicationPreloadStatus preload_res =
|
||||
flipper_application_preload(*fal_app, plugin_path);
|
||||
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to preload plugin: %s", plugin_path);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_application_is_plugin(*fal_app)) {
|
||||
FURI_LOG_E(TAG, "Plugin file is not a library");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(*fal_app);
|
||||
if(load_status != FlipperApplicationLoadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to load plugin file");
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "is mapped to memory");
|
||||
app_descriptor = flipper_application_plugin_get_descriptor(*fal_app);
|
||||
if(strcmp(app_descriptor->appid, application_id) != 0) {
|
||||
FURI_LOG_E(TAG, "Application id mismatch %s", application_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if(app_descriptor->ep_api_version != api_version) {
|
||||
FURI_LOG_E(TAG, "API version mismatch %lu", api_version);
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Loaded plugin for appid '%s', API %lu",
|
||||
app_descriptor->appid,
|
||||
app_descriptor->ep_api_version);
|
||||
return_value = true;
|
||||
} while(false);
|
||||
|
||||
//Free the applciation if there was an error, otherwise return the app descriptor.
|
||||
if(return_value) {
|
||||
return app_descriptor;
|
||||
} else {
|
||||
if(*fal_app) {
|
||||
flipper_application_free(*fal_app);
|
||||
*fal_app = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void shared_plugin_unload(void** flipper_application_pointer, const void** plugin_pointer) {
|
||||
//Free the flipper application.
|
||||
if(*flipper_application_pointer) {
|
||||
flipper_application_free(*flipper_application_pointer);
|
||||
*flipper_application_pointer = NULL;
|
||||
}
|
||||
|
||||
//Free the pointer.
|
||||
if(*plugin_pointer) {
|
||||
*plugin_pointer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool shared_plugin_load(
|
||||
void** flipper_application_pointer,
|
||||
const void** plugin_pointer,
|
||||
ProtoPirateSharedPlugin plugin_type,
|
||||
const char* txrx_path) {
|
||||
const char* application_id = NULL;
|
||||
const char* plugin_path = NULL;
|
||||
uint32_t api_version = 0;
|
||||
|
||||
if(*plugin_pointer) return true;
|
||||
|
||||
switch(plugin_type) {
|
||||
case ProtoPirateSharedPluginsConfig: {
|
||||
application_id = PROTOPIRATE_CONFIG_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_CONFIG_PLUGIN_API_VERSION;
|
||||
plugin_path = CONFIG_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsSavedInfo: {
|
||||
application_id = PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_SAVED_INFO_PLUGIN_API_VERSION;
|
||||
plugin_path = SAVED_INFO_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsAbout: {
|
||||
application_id = PROTOPIRATE_ABOUT_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_ABOUT_PLUGIN_API_VERSION;
|
||||
plugin_path = ABOUT_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
case ProtoPirateSharedPluginsEmulate: {
|
||||
application_id = PROTOPIRATE_EMULATE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_EMULATE_PLUGIN_API_VERSION;
|
||||
plugin_path = EMULATE_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ProtoPirateSharedPluginsSubDecode: {
|
||||
application_id = PROTOPIRATE_TOOL_SCENE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_TOOL_SCENE_PLUGIN_API_VERSION;
|
||||
plugin_path = SUB_DECODE_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
case ProtoPirateSharedPluginsTimingTuner: {
|
||||
application_id = PROTOPIRATE_TOOL_SCENE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_TOOL_SCENE_PLUGIN_API_VERSION;
|
||||
plugin_path = TIMING_TUNER_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ProtoPirateSharedPluginsPSABruteforce: {
|
||||
application_id = PROTOPIRATE_PSA_BF_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_PSA_BF_PLUGIN_API_VERSION;
|
||||
plugin_path = PSA_BF_PLUGIN_PATH;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsTXRX: {
|
||||
application_id = PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION;
|
||||
plugin_path = txrx_path;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "Loading plugin: %s", plugin_path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperApplication* fal_app = flipper_application_alloc(storage, firmware_api_interface);
|
||||
bool return_value = false;
|
||||
do {
|
||||
//Load the FAP
|
||||
const FlipperAppPluginDescriptor* app_descriptor =
|
||||
load_plugin_fal(&fal_app, plugin_path, application_id, api_version);
|
||||
if(app_descriptor) {
|
||||
//Get the Plugin and assign it.
|
||||
if(plugin_type == ProtoPirateSharedPluginsConfig) {
|
||||
const ProtoPirateConfigPlugin* plugin_config = app_descriptor->entry_point;
|
||||
if(!plugin_config || !plugin_config->on_enter) {
|
||||
FURI_LOG_E(TAG, "Config plugin entry point is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_config;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) {
|
||||
const ProtoPirateSavedInfoPlugin* plugin_saved_info = app_descriptor->entry_point;
|
||||
if(!plugin_saved_info || !plugin_saved_info->on_enter) {
|
||||
FURI_LOG_E(TAG, "Saved Info plugin entry point is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_saved_info;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsAbout) {
|
||||
const ProtoPirateAboutPlugin* plugin_about = app_descriptor->entry_point;
|
||||
if(!plugin_about || !plugin_about->on_enter) {
|
||||
FURI_LOG_E(TAG, "About plugin entry point is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_about;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
else if(plugin_type == ProtoPirateSharedPluginsEmulate) {
|
||||
const ProtoPirateEmulatePlugin* plugin_emulate = app_descriptor->entry_point;
|
||||
if(!plugin_emulate || !plugin_emulate->on_enter) {
|
||||
FURI_LOG_E(TAG, "Emulate plugin entry point is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_emulate;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if(
|
||||
plugin_type == ProtoPirateSharedPluginsSubDecode
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
|| plugin_type == ProtoPirateSharedPluginsTimingTuner
|
||||
#endif
|
||||
) {
|
||||
const ProtoPirateToolScenePlugin* plugin_tool_scene = app_descriptor->entry_point;
|
||||
if(!plugin_tool_scene || !plugin_tool_scene->on_enter) {
|
||||
FURI_LOG_E(TAG, "Tool Scene plugin entry point is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_tool_scene;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsPSABruteforce) {
|
||||
const ProtoPiratePsaBfPlugin* plugin_psa_bf = app_descriptor->entry_point;
|
||||
if(!plugin_psa_bf || !plugin_psa_bf->needs_bruteforce) {
|
||||
FURI_LOG_E(TAG, "PSA plugin entry needs_bruteforce is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_psa_bf;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsTXRX) {
|
||||
const ProtoPirateProtocolPlugin* plugin_txrx = app_descriptor->entry_point;
|
||||
if(!plugin_txrx || !plugin_txrx->registry) {
|
||||
FURI_LOG_E(TAG, "Protocol plugin registry entry is invalid");
|
||||
} else {
|
||||
*plugin_pointer = plugin_txrx;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
//Free the plugin if there was an error, otherwise we are done!
|
||||
*flipper_application_pointer = fal_app;
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return return_value;
|
||||
}
|
||||
bool shared_plugin_handle_navigation_events(
|
||||
SceneManager* scene_manager,
|
||||
ViewDispatcher* view_dispatcher,
|
||||
SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventPluginNavigateEmulate) {
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
scene_manager_next_scene(scene_manager, ProtoPirateSceneEmulate);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if(event.event == ProtoPirateCustomEventPluginNavigateConfig) {
|
||||
scene_manager_next_scene(scene_manager, ProtoPirateSceneReceiverConfig);
|
||||
return true;
|
||||
} else if(event.event == ProtoPirateCustomEventPluginNavigateBack) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
return true;
|
||||
} else if(event.event == ProtoPirateCustomEventPluginNavigateStopApp) {
|
||||
scene_manager_stop(scene_manager);
|
||||
view_dispatcher_stop(view_dispatcher);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "../defines.h"
|
||||
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#include "scenes/plugins/protopirate_emulate_plugin.h"
|
||||
#endif
|
||||
#include "scenes/plugins/protopirate_config_plugin.h"
|
||||
#include "scenes/plugins/protopirate_saved_info_plugin.h"
|
||||
#include "scenes/plugins/protopirate_about_plugin.h"
|
||||
#include "scenes/plugins/protopirate_psa_bf_plugin.h"
|
||||
#include "scenes/plugins/protopirate_tool_scene_plugin.h"
|
||||
|
||||
#define CONFIG_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_config.fal")
|
||||
#define SAVED_INFO_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_saved_info.fal")
|
||||
#define ABOUT_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_about.fal")
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_emulate.fal")
|
||||
#endif
|
||||
#define SUB_DECODE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_sub_decode.fal")
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
#define TIMING_TUNER_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_timing_tuner.fal")
|
||||
#endif
|
||||
#define PSA_BF_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_bf.fal")
|
||||
|
||||
typedef enum ProtoPirateSharedPlugin {
|
||||
ProtoPirateSharedPluginsConfig,
|
||||
ProtoPirateSharedPluginsSavedInfo,
|
||||
ProtoPirateSharedPluginsAbout,
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ProtoPirateSharedPluginsEmulate,
|
||||
#endif
|
||||
ProtoPirateSharedPluginsToolScene,
|
||||
ProtoPirateSharedPluginsSubDecode,
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
ProtoPirateSharedPluginsTimingTuner,
|
||||
#endif
|
||||
ProtoPirateSharedPluginsPSABruteforce,
|
||||
ProtoPirateSharedPluginsTXRX,
|
||||
} ProtoPirateSharedPlugin;
|
||||
|
||||
bool shared_plugin_load(
|
||||
void** flipper_application_pointer,
|
||||
const void** plugin_pointer,
|
||||
ProtoPirateSharedPlugin plugin_type,
|
||||
const char* txrx_path);
|
||||
void shared_plugin_unload(void** flipper_application_pointer, const void** plugin_pointer);
|
||||
bool shared_plugin_handle_navigation_events(
|
||||
SceneManager* scene_manager,
|
||||
ViewDispatcher* view_dispatcher,
|
||||
SceneManagerEvent event);
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "protopirate_txrx.h"
|
||||
#include "../protocols/protocol_items.h"
|
||||
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -61,7 +60,9 @@ void protopirate_unload_protocol_plugin(ProtoPirateApp* app) {
|
||||
app->txrx->protocol_plugin->release();
|
||||
}
|
||||
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsTXRX);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->txrx->protocol_plugin_flipper_application,
|
||||
(const void**)&app->txrx->protocol_plugin);
|
||||
}
|
||||
|
||||
static bool protopirate_ensure_protocol_registry_plugin(
|
||||
@@ -91,7 +92,11 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
}
|
||||
|
||||
const char* plugin_path = protopirate_get_registry_plugin_path(route);
|
||||
shared_plugin_load(app, ProtoPirateSharedPluginsTXRX, plugin_path);
|
||||
shared_plugin_load(
|
||||
(void**)&app->txrx->protocol_plugin_flipper_application,
|
||||
(const void**)&app->txrx->protocol_plugin,
|
||||
ProtoPirateSharedPluginsTXRX,
|
||||
plugin_path);
|
||||
|
||||
if(app->txrx->protocol_plugin->kind != ProtoPirateProtocolPluginKindRx) {
|
||||
FURI_LOG_E(TAG, "Protocol plugin kind mismatch for RX route");
|
||||
@@ -157,7 +162,11 @@ static bool protopirate_ensure_tx_protocol_plugin(
|
||||
protopirate_unload_protocol_plugin(app);
|
||||
}
|
||||
|
||||
shared_plugin_load(app, ProtoPirateSharedPluginsTXRX, plugin_path);
|
||||
shared_plugin_load(
|
||||
(void**)&app->txrx->protocol_plugin_flipper_application,
|
||||
(const void**)&app->txrx->protocol_plugin,
|
||||
ProtoPirateSharedPluginsTXRX,
|
||||
plugin_path);
|
||||
|
||||
const SubGhzProtocol* tx_protocol = app->txrx->protocol_plugin->registry->items[0];
|
||||
if(!tx_protocol || !tx_protocol->encoder || !tx_protocol->encoder->alloc ||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "../protocols/protocols_common.h"
|
||||
#include "../scenes/plugins/protopirate_psa_bf_plugin.h"
|
||||
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define TAG "PPPsaBfHost"
|
||||
@@ -114,7 +113,11 @@ static const ProtoPiratePsaBfHostApi protopirate_psa_bf_host_api = {
|
||||
};
|
||||
|
||||
bool protopirate_psa_bf_plugin_ensure_loaded(ProtoPirateApp* app) {
|
||||
if(shared_plugin_load(app, ProtoPirateSharedPluginsPSABruteforce, NULL)) {
|
||||
if(shared_plugin_load(
|
||||
(void**)&app->psa_bf_plugin_flipper_application,
|
||||
(const void**)&app->psa_bf_plugin,
|
||||
ProtoPirateSharedPluginsPSABruteforce,
|
||||
NULL)) {
|
||||
app->psa_bf_plugin->set_host_api(&protopirate_psa_bf_host_api);
|
||||
return true;
|
||||
} else {
|
||||
@@ -127,7 +130,9 @@ void protopirate_psa_bf_plugin_unload_if_idle(ProtoPirateApp* app) {
|
||||
app->psa_bf_plugin->is_running(app)) {
|
||||
return;
|
||||
}
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsPSABruteforce);
|
||||
|
||||
shared_plugin_unload(
|
||||
(void**)&app->psa_bf_plugin_flipper_application, (const void**)&app->psa_bf_plugin);
|
||||
}
|
||||
|
||||
void protopirate_psa_bf_context_release(ProtoPirateApp* app) {
|
||||
@@ -135,5 +140,6 @@ void protopirate_psa_bf_context_release(ProtoPirateApp* app) {
|
||||
if(app->psa_bf_plugin && app->psa_bf_plugin->context_release) {
|
||||
app->psa_bf_plugin->context_release(app);
|
||||
}
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsPSABruteforce);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->psa_bf_plugin_flipper_application, (const void**)&app->psa_bf_plugin);
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <furi.h>
|
||||
#include "../defines.h"
|
||||
#include "../protocols/protocols_common.h"
|
||||
|
||||
#define TAG "PPSettings"
|
||||
@@ -22,7 +21,9 @@ void protopirate_settings_set_defaults(ProtoPirateSettings* settings) {
|
||||
settings->emulate_feature_enabled = false;
|
||||
settings->check_saved = false;
|
||||
settings->datetime_filenames = false;
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
settings->car_model_index = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void protopirate_settings_load(ProtoPirateSettings* settings) {
|
||||
@@ -135,13 +136,14 @@ void protopirate_settings_load(ProtoPirateSettings* settings) {
|
||||
}
|
||||
settings->datetime_filenames = (datetime_filenames_temp == 1);
|
||||
|
||||
// Read Selected Car Model
|
||||
// Read Selected Car Model
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
uint32_t car_model_index_temp = 0;
|
||||
if(!flipper_format_read_uint32(ff, "CarModelIndex", &car_model_index_temp, 1)) {
|
||||
car_model_index_temp = 0;
|
||||
}
|
||||
settings->car_model_index = car_model_index_temp;
|
||||
|
||||
#endif
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Settings loaded: freq=%lu, preset=%u, auto_save=%d, hopping=%d, emulate=%d, check_saved=%d, sound = %d",
|
||||
@@ -234,12 +236,14 @@ void protopirate_settings_save(ProtoPirateSettings* settings) {
|
||||
if(!flipper_format_write_uint32(ff, "DateTimeFilenames", &datetime_filenames_temp, 1)) {
|
||||
FURI_LOG_E(TAG, "Failed to write Date Time Filenames");
|
||||
}
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
uint32_t car_model_index_temp = settings->car_model_index;
|
||||
if(!flipper_format_write_uint32(ff, "CarModelIndex", &car_model_index_temp, 1)) {
|
||||
FURI_LOG_E(TAG, "Failed to write car model");
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
write_ok = true;
|
||||
|
||||
FURI_LOG_I(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// helpers/protopirate_settings.h
|
||||
#pragma once
|
||||
|
||||
#include "../defines.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -19,7 +20,9 @@ typedef struct {
|
||||
bool emulate_feature_enabled;
|
||||
bool check_saved;
|
||||
bool datetime_filenames;
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
uint16_t car_model_index;
|
||||
#endif
|
||||
} ProtoPirateSettings;
|
||||
|
||||
void protopirate_settings_load(ProtoPirateSettings* settings);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "protopirate_psa_bf_host.h"
|
||||
#include "radio_device_loader.h"
|
||||
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define TAG "PPToolScene"
|
||||
@@ -126,14 +125,25 @@ static bool protopirate_tool_scene_plugin_ensure_loaded(
|
||||
if(app->tool_scene_plugin->release) {
|
||||
app->tool_scene_plugin->release(app);
|
||||
}
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsToolScene);
|
||||
|
||||
shared_plugin_unload(
|
||||
(void**)&app->tool_scene_plugin_flipper_application,
|
||||
(const void**)&app->tool_scene_plugin);
|
||||
}
|
||||
|
||||
if(kind == ProtoPirateToolScenePluginKindSubDecode)
|
||||
shared_plugin_load(app, ProtoPirateSharedPluginsSubDecode, NULL);
|
||||
shared_plugin_load(
|
||||
(void**)&app->tool_scene_plugin_flipper_application,
|
||||
(const void**)&app->tool_scene_plugin,
|
||||
ProtoPirateSharedPluginsSubDecode,
|
||||
NULL);
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
else if(kind == ProtoPirateToolScenePluginKindTimingTuner)
|
||||
shared_plugin_load(app, ProtoPirateSharedPluginsTimingTuner, NULL);
|
||||
shared_plugin_load(
|
||||
(void**)&app->tool_scene_plugin_flipper_application,
|
||||
(const void**)&app->tool_scene_plugin,
|
||||
ProtoPirateSharedPluginsTimingTuner,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
app->tool_scene_plugin_kind = kind;
|
||||
@@ -141,40 +151,10 @@ static bool protopirate_tool_scene_plugin_ensure_loaded(
|
||||
return true;
|
||||
}
|
||||
|
||||
static void protopirate_tool_scene_apply_pending_nav(ProtoPirateApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
const uint8_t nav = app->tool_scene_nav_pending;
|
||||
if(nav == TOOL_SCENE_NAV_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t target = app->tool_scene_nav_target;
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_NONE;
|
||||
app->tool_scene_nav_target = 0;
|
||||
|
||||
switch(nav) {
|
||||
case TOOL_SCENE_NAV_POP:
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
break;
|
||||
case TOOL_SCENE_NAV_NEXT:
|
||||
scene_manager_next_scene(app->scene_manager, target);
|
||||
break;
|
||||
case TOOL_SCENE_NAV_SEARCH_PREVIOUS:
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, target);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_tool_scene_on_enter(void* context, ProtoPirateToolScenePluginKind kind) {
|
||||
ProtoPirateApp* app = context;
|
||||
furi_check(app);
|
||||
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_NONE;
|
||||
app->tool_scene_nav_target = 0;
|
||||
|
||||
if(!protopirate_tool_scene_plugin_ensure_loaded(app, kind) || !app->tool_scene_plugin) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
@@ -182,7 +162,6 @@ bool protopirate_tool_scene_on_enter(void* context, ProtoPirateToolScenePluginKi
|
||||
}
|
||||
|
||||
app->tool_scene_plugin->on_enter(app);
|
||||
protopirate_tool_scene_apply_pending_nav(app);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -193,7 +172,6 @@ bool protopirate_tool_scene_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
const bool consumed = app->tool_scene_plugin->on_event(app, event);
|
||||
protopirate_tool_scene_apply_pending_nav(app);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@@ -210,7 +188,9 @@ void protopirate_tool_scene_on_exit(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsToolScene);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->tool_scene_plugin_flipper_application,
|
||||
(const void**)&app->tool_scene_plugin);
|
||||
}
|
||||
|
||||
void protopirate_tool_scene_plugin_release(ProtoPirateApp* app) {
|
||||
@@ -219,5 +199,7 @@ void protopirate_tool_scene_plugin_release(ProtoPirateApp* app) {
|
||||
if(app->tool_scene_plugin && app->tool_scene_plugin->release) {
|
||||
app->tool_scene_plugin->release(app);
|
||||
}
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsToolScene);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->tool_scene_plugin_flipper_application,
|
||||
(const void**)&app->tool_scene_plugin);
|
||||
}
|
||||
@@ -58,13 +58,13 @@ void protopirate_get_frequency_modulation_str(
|
||||
size_t modulation_size) {
|
||||
furi_check(app);
|
||||
|
||||
if(frequency && frequency_size > 0) {
|
||||
if(frequency) {
|
||||
unsigned long mhz = (unsigned long)((app->txrx->preset->frequency / 1000000UL) % 1000UL);
|
||||
unsigned long khz = (unsigned long)((app->txrx->preset->frequency / 10000UL) % 100UL);
|
||||
snprintf(frequency, frequency_size, "%03lu.%02lu", mhz, khz);
|
||||
}
|
||||
|
||||
if(modulation && modulation_size > 0) {
|
||||
if(modulation) {
|
||||
snprintf(
|
||||
modulation, modulation_size, "%.2s", furi_string_get_cstr(app->txrx->preset->name));
|
||||
}
|
||||
@@ -73,19 +73,20 @@ void protopirate_get_frequency_modulation_str(
|
||||
void protopirate_get_frequency_modulation(
|
||||
ProtoPirateApp* app,
|
||||
FuriString* frequency,
|
||||
FuriString* modulation) {
|
||||
size_t frequency_size,
|
||||
FuriString* modulation,
|
||||
size_t modulation_size) {
|
||||
furi_check(app);
|
||||
|
||||
char frequency_buf[16] = {0};
|
||||
char modulation_buf[8] = {0};
|
||||
protopirate_get_frequency_modulation_str(
|
||||
app, frequency_buf, sizeof(frequency_buf), modulation_buf, sizeof(modulation_buf));
|
||||
protopirate_get_frequency_modulation_str(app, frequency_buf, 16, modulation_buf, 8);
|
||||
|
||||
if(frequency != NULL) {
|
||||
furi_string_set_str(frequency, frequency_buf);
|
||||
memcpy(frequency, frequency_buf, frequency_size);
|
||||
}
|
||||
if(modulation != NULL) {
|
||||
furi_string_set_str(modulation, modulation_buf);
|
||||
memcpy(modulation, modulation_buf, modulation_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ void protopirate_preset_init(
|
||||
void protopirate_get_frequency_modulation(
|
||||
ProtoPirateApp* app,
|
||||
FuriString* frequency,
|
||||
FuriString* modulation);
|
||||
size_t frequency_size,
|
||||
FuriString* modulation,
|
||||
size_t modulation_size);
|
||||
|
||||
void protopirate_get_frequency_modulation_str(
|
||||
ProtoPirateApp* app,
|
||||
char* frequency,
|
||||
|
||||
@@ -31,22 +31,19 @@ typedef enum {
|
||||
ProtoPirateCustomEventReceiverInfoUpdate,
|
||||
ProtoPirateCustomEventReceiverInfoEmulate,
|
||||
ProtoPirateCustomEventSavedInfoDelete,
|
||||
ProtoPirateCustomEventSavedInfoExit,
|
||||
//Bruteforcing PSA & Renault
|
||||
ProtoPirateCustomEventBruteforceStart,
|
||||
ProtoPirateCustomEventBruteforceComplete,
|
||||
// Emulator
|
||||
ProtoPirateCustomEventSavedInfoEmulate,
|
||||
ProtoPirateCustomEventSavedInfoEmulateDelayedStart,
|
||||
ProtoPirateCustomEventEmulateTransmit,
|
||||
ProtoPirateCustomEventEmulateStop,
|
||||
ProtoPirateCustomEventEmulateExit,
|
||||
ProtoPirateCustomEventSavedInfoEmulate,
|
||||
// Sub decode
|
||||
ProtoPirateCustomEventSubDecodeUpdate,
|
||||
ProtoPirateCustomEventSubDecodeSave,
|
||||
ProtoPirateCustomEventSubDecodeEmulate,
|
||||
ProtoPirateCustomEventSubDecodeSaveConfirm,
|
||||
ProtoPirateCustomEventSubDecodeEmulateDelayedStart,
|
||||
// File Browser
|
||||
ProtoPirateCustomEventSavedFileSelected,
|
||||
// Need saving confirmation
|
||||
@@ -54,6 +51,11 @@ typedef enum {
|
||||
ProtoPirateCustomEventSceneExit,
|
||||
// About scene
|
||||
ProtoPirateCustomEventAboutToggleEmulate,
|
||||
//Plugin Scenes
|
||||
ProtoPirateCustomEventPluginNavigateBack,
|
||||
ProtoPirateCustomEventPluginNavigateEmulate,
|
||||
ProtoPirateCustomEventPluginNavigateConfig,
|
||||
ProtoPirateCustomEventPluginNavigateStopApp,
|
||||
} ProtoPirateCustomEvent;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "../defines.h"
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
#include "helpers/variable_item_list.h"
|
||||
#include <gui/elements.h>
|
||||
#include <gui/canvas.h>
|
||||
@@ -639,3 +642,4 @@ void* variable_item_get_context(VariableItem* item) {
|
||||
furi_check(item);
|
||||
return item->context;
|
||||
}
|
||||
#endif
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../subaru.h"
|
||||
#include "../star_line.h"
|
||||
#include "../honda_v1.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_am_items[] = {
|
||||
&chrysler_protocol_v0,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../protopirate_protocol_plugins.h"
|
||||
#include "../protocols_common.h"
|
||||
#include "../vag.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_am_vag_items[] = {
|
||||
&vag_protocol,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../ford_v2.h"
|
||||
#include "../ford_v3.h"
|
||||
#include "../honda_v2.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_fm_f4_items[] = {
|
||||
&ford_protocol_v1,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../protopirate_protocol_plugins.h"
|
||||
#include "../protocols_common.h"
|
||||
#include "../honda_static.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_fm_honda1_items[] = {
|
||||
&honda_static_protocol,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "../mazda_v0.h"
|
||||
#include "../psa.h"
|
||||
#include "../renault_v1.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_fm_items[] = {
|
||||
&subghz_protocol_scher_khan,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../protopirate_protocol_plugins.h"
|
||||
#include "../protocols_common.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
#ifndef PP_TX_PROTOCOL_HEADER
|
||||
#error "PP_TX_PROTOCOL_HEADER must be defined for TX protocol plugins"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <lib/subghz/types.h>
|
||||
#include "protocol_items.h"
|
||||
|
||||
|
||||
+9
-2
@@ -1,9 +1,16 @@
|
||||
#include "../defines.h"
|
||||
#include "vag.h"
|
||||
#include "aut64.h"
|
||||
#include "protocols_common.h"
|
||||
#include <string.h>
|
||||
#include <lib/subghz/subghz_keystore.h>
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
#define PROTOPIRATE_VAG_KEYS_FILE_NAME APP_ASSETS_PATH("keystore/vag")
|
||||
#else
|
||||
#define PROTOPIRATE_VAG_KEYS_FILE_NAME APP_ASSETS_PATH("vag")
|
||||
#endif
|
||||
|
||||
#define TAG "VAGProtocol"
|
||||
|
||||
#define VAG_ENCODER_UPLOAD_TYPE12_SIZE 635
|
||||
@@ -548,7 +555,7 @@ void* subghz_protocol_decoder_vag_alloc(SubGhzEnvironment* environment) {
|
||||
instance->decrypted = false;
|
||||
instance->key_idx = 0xFF;
|
||||
|
||||
protocol_vag_load_keys(APP_ASSETS_PATH("vag"));
|
||||
protocol_vag_load_keys(PROTOPIRATE_VAG_KEYS_FILE_NAME);
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -1544,7 +1551,7 @@ void* subghz_protocol_encoder_vag_alloc(SubGhzEnvironment* environment) {
|
||||
instance->is_running = false;
|
||||
instance->key_idx = 0xFF;
|
||||
|
||||
protocol_vag_load_keys(APP_ASSETS_PATH("vag"));
|
||||
protocol_vag_load_keys(APP_ASSETS_PATH("keystore/vag"));
|
||||
|
||||
FURI_LOG_I(TAG, "VAG encoder alloc complete, keys loaded: %d", protocol_vag_keys_loaded);
|
||||
|
||||
|
||||
+21
-295
@@ -8,298 +8,11 @@
|
||||
#include "helpers/protopirate_psa_bf_host.h"
|
||||
#include "helpers/protopirate_views.h"
|
||||
#include "helpers/protopirate_radio.h"
|
||||
#include "helpers/protopirate_plugins.h"
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "PPApp"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Plugin load / unload
|
||||
// -----------------------------------------------------------------------------
|
||||
const FlipperAppPluginDescriptor* load_plugin_fal(
|
||||
FlipperApplication** fal_app,
|
||||
const char* plugin_path,
|
||||
const char* application_id,
|
||||
uint32_t api_version) {
|
||||
const FlipperAppPluginDescriptor* app_descriptor;
|
||||
|
||||
bool return_value = false;
|
||||
do {
|
||||
FlipperApplicationPreloadStatus preload_res =
|
||||
flipper_application_preload(*fal_app, plugin_path);
|
||||
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to preload plugin: %s", plugin_path);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_application_is_plugin(*fal_app)) {
|
||||
FURI_LOG_E(TAG, "Plugin file is not a library");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(*fal_app);
|
||||
if(load_status != FlipperApplicationLoadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to load plugin file");
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "is mapped to memory");
|
||||
app_descriptor = flipper_application_plugin_get_descriptor(*fal_app);
|
||||
if(strcmp(app_descriptor->appid, application_id) != 0) {
|
||||
FURI_LOG_E(TAG, "Application id mismatch %s", application_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if(app_descriptor->ep_api_version != api_version) {
|
||||
FURI_LOG_E(TAG, "API version mismatch %lu", api_version);
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Loaded plugin for appid '%s', API %lu",
|
||||
app_descriptor->appid,
|
||||
app_descriptor->ep_api_version);
|
||||
return_value = true;
|
||||
} while(false);
|
||||
|
||||
//Free the applciation if there was an error, otherwise return the app descriptor.
|
||||
if(return_value) {
|
||||
return app_descriptor;
|
||||
} else {
|
||||
if(*fal_app) {
|
||||
flipper_application_free(*fal_app);
|
||||
*fal_app = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void shared_plugin_unload(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type) {
|
||||
//Clear the invalid reference to the plugin.
|
||||
FlipperApplication** fal_needs_free = NULL;
|
||||
switch(plugin_type) {
|
||||
case ProtoPirateSharedPluginsConfig: {
|
||||
fal_needs_free = &app->plugin_flipper_application;
|
||||
app->config_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsSavedInfo: {
|
||||
fal_needs_free = &app->plugin_flipper_application;
|
||||
app->saved_info_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsAbout: {
|
||||
fal_needs_free = &app->plugin_flipper_application;
|
||||
app->about_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
case ProtoPirateSharedPluginsEmulate: {
|
||||
fal_needs_free = &app->plugin_flipper_application;
|
||||
app->emulate_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ProtoPirateSharedPluginsToolScene:
|
||||
case ProtoPirateSharedPluginsSubDecode:
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
case ProtoPirateSharedPluginsTimingTuner:
|
||||
#endif
|
||||
{
|
||||
fal_needs_free = &app->tool_scene_plugin_flipper_application;
|
||||
app->tool_scene_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsPSABruteforce: {
|
||||
fal_needs_free = &app->psa_bf_plugin_flipper_application;
|
||||
app->psa_bf_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsTXRX: {
|
||||
fal_needs_free = &app->txrx->protocol_plugin_flipper_application;
|
||||
app->txrx->protocol_plugin = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
//Free the flipper application.
|
||||
if(*fal_needs_free) {
|
||||
flipper_application_free(*fal_needs_free);
|
||||
*fal_needs_free = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool shared_plugin_load(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateSharedPlugin plugin_type,
|
||||
const char* txrx_path) {
|
||||
//Get the APPID and API VERSION for the Plugin we are loading.
|
||||
const char* application_id = NULL;
|
||||
const char* plugin_path = NULL;
|
||||
uint32_t api_version = 0;
|
||||
FlipperApplication** fal_needs_alloc = NULL;
|
||||
|
||||
switch(plugin_type) {
|
||||
case ProtoPirateSharedPluginsConfig: {
|
||||
if(app->config_plugin) return true;
|
||||
application_id = PROTOPIRATE_CONFIG_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_CONFIG_PLUGIN_API_VERSION;
|
||||
plugin_path = CONFIG_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsSavedInfo: {
|
||||
if(app->saved_info_plugin) return true;
|
||||
application_id = PROTOPIRATE_SAVED_INFO_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_SAVED_INFO_PLUGIN_API_VERSION;
|
||||
plugin_path = SAVED_INFO_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsAbout: {
|
||||
if(app->about_plugin) return true;
|
||||
application_id = PROTOPIRATE_ABOUT_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_ABOUT_PLUGIN_API_VERSION;
|
||||
plugin_path = ABOUT_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
case ProtoPirateSharedPluginsEmulate: {
|
||||
if(app->emulate_plugin) return true;
|
||||
application_id = PROTOPIRATE_EMULATE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_EMULATE_PLUGIN_API_VERSION;
|
||||
plugin_path = EMULATE_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ProtoPirateSharedPluginsSubDecode: {
|
||||
if(app->tool_scene_plugin) return true;
|
||||
application_id = PROTOPIRATE_TOOL_SCENE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_TOOL_SCENE_PLUGIN_API_VERSION;
|
||||
plugin_path = SUB_DECODE_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->tool_scene_plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
case ProtoPirateSharedPluginsTimingTuner: {
|
||||
if(app->tool_scene_plugin) return true;
|
||||
application_id = PROTOPIRATE_TOOL_SCENE_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_TOOL_SCENE_PLUGIN_API_VERSION;
|
||||
plugin_path = TIMING_TUNER_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->tool_scene_plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case ProtoPirateSharedPluginsPSABruteforce: {
|
||||
if(app->psa_bf_plugin) return true;
|
||||
application_id = PROTOPIRATE_PSA_BF_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_PSA_BF_PLUGIN_API_VERSION;
|
||||
plugin_path = PSA_BF_PLUGIN_PATH;
|
||||
fal_needs_alloc = &app->psa_bf_plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSharedPluginsTXRX: {
|
||||
if(app->txrx->protocol_plugin) return true;
|
||||
application_id = PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID;
|
||||
api_version = PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION;
|
||||
plugin_path = txrx_path;
|
||||
fal_needs_alloc = &app->txrx->protocol_plugin_flipper_application;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "Loading plugin: %s", plugin_path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperApplication* fal_app = flipper_application_alloc(storage, firmware_api_interface);
|
||||
bool return_value = false;
|
||||
do {
|
||||
//Load the FAP
|
||||
const FlipperAppPluginDescriptor* app_descriptor =
|
||||
load_plugin_fal(&fal_app, plugin_path, application_id, api_version);
|
||||
if(app_descriptor) {
|
||||
//Get the Plugin and assign it.
|
||||
if(plugin_type == ProtoPirateSharedPluginsConfig) {
|
||||
const ProtoPirateConfigPlugin* plugin_config = app_descriptor->entry_point;
|
||||
if(!plugin_config || !plugin_config->on_enter) {
|
||||
FURI_LOG_E(TAG, "Config plugin entry point is invalid");
|
||||
} else {
|
||||
app->config_plugin = plugin_config;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsSavedInfo) {
|
||||
const ProtoPirateSavedInfoPlugin* plugin_saved_info = app_descriptor->entry_point;
|
||||
if(!plugin_saved_info || !plugin_saved_info->on_enter) {
|
||||
FURI_LOG_E(TAG, "Saved Info plugin entry point is invalid");
|
||||
} else {
|
||||
app->saved_info_plugin = plugin_saved_info;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsAbout) {
|
||||
const ProtoPirateAboutPlugin* plugin_about = app_descriptor->entry_point;
|
||||
if(!plugin_about || !plugin_about->on_enter) {
|
||||
FURI_LOG_E(TAG, "About plugin entry point is invalid");
|
||||
} else {
|
||||
app->about_plugin = plugin_about;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
else if(plugin_type == ProtoPirateSharedPluginsEmulate) {
|
||||
const ProtoPirateEmulatePlugin* plugin_emulate = app_descriptor->entry_point;
|
||||
if(!plugin_emulate || !plugin_emulate->on_enter) {
|
||||
FURI_LOG_E(TAG, "Emulate plugin entry point is invalid");
|
||||
} else {
|
||||
app->emulate_plugin = plugin_emulate;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if(
|
||||
plugin_type == ProtoPirateSharedPluginsSubDecode
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
|| plugin_type == ProtoPirateSharedPluginsTimingTuner
|
||||
#endif
|
||||
) {
|
||||
const ProtoPirateToolScenePlugin* plugin_tool_scene = app_descriptor->entry_point;
|
||||
if(!plugin_tool_scene || !plugin_tool_scene->on_enter) {
|
||||
FURI_LOG_E(TAG, "Tool Scene plugin entry point is invalid");
|
||||
} else {
|
||||
app->tool_scene_plugin = plugin_tool_scene;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsPSABruteforce) {
|
||||
const ProtoPiratePsaBfPlugin* plugin_psa_bf = app_descriptor->entry_point;
|
||||
if(!plugin_psa_bf || !plugin_psa_bf->needs_bruteforce) {
|
||||
FURI_LOG_E(TAG, "PSA plugin entry needs_bruteforce is invalid");
|
||||
} else {
|
||||
app->psa_bf_plugin = plugin_psa_bf;
|
||||
return_value = true;
|
||||
}
|
||||
} else if(plugin_type == ProtoPirateSharedPluginsTXRX) {
|
||||
const ProtoPirateProtocolPlugin* plugin_txrx = app_descriptor->entry_point;
|
||||
if(!plugin_txrx || !plugin_txrx->registry) {
|
||||
FURI_LOG_E(TAG, "Protocol plugin registry entry is invalid");
|
||||
} else {
|
||||
app->txrx->protocol_plugin = plugin_txrx;
|
||||
return_value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
//Free the plugin if there was an error, otherwise we are done!
|
||||
if(fal_needs_alloc) *fal_needs_alloc = fal_app;
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static bool protopirate_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
@@ -451,9 +164,16 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
app->psa_bf_plugin = NULL;
|
||||
app->tool_scene_plugin_flipper_application = NULL;
|
||||
app->tool_scene_plugin = NULL;
|
||||
app->variable_item_list = NULL;
|
||||
|
||||
//Load the models database, get the count of the models for the list.
|
||||
if(shared_plugin_load(app, ProtoPirateSharedPluginsConfig, NULL) && app->config_plugin) {
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
if(shared_plugin_load(
|
||||
(void**)&app->plugin_flipper_application,
|
||||
(const void**)&app->config_plugin,
|
||||
ProtoPirateSharedPluginsConfig,
|
||||
NULL) &&
|
||||
app->config_plugin) {
|
||||
app->car_models_count = app->config_plugin->car_model_get_count();
|
||||
} else {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
@@ -463,7 +183,6 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
app->selected_model->name = NULL;
|
||||
app->selected_model->preset = NULL; // important initialization
|
||||
app->selected_model->index = 0; // optional but clean
|
||||
app->variable_item_list = NULL;
|
||||
|
||||
//Grab selected car model.
|
||||
if(app->config_plugin) {
|
||||
@@ -490,11 +209,15 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
}
|
||||
|
||||
//Kill the config plugin now.
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsConfig);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->plugin_flipper_application, (const void**)&app->config_plugin);
|
||||
} else {
|
||||
#endif
|
||||
//Preset set in Config.
|
||||
protopirate_preset_init(app, preset_name, frequency, preset_data, preset_data_size);
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
}
|
||||
#endif
|
||||
|
||||
// Apply hopping state from settings
|
||||
app->txrx->hopper_state = settings.hopping_enabled ? ProtoPirateHopperStateRunning :
|
||||
@@ -530,6 +253,7 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
#endif
|
||||
|
||||
//Get the selected Model, and get the preset to save.
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
if(app->selected_model && app->selected_model->index) {
|
||||
//Get Preset Index before model was selected.
|
||||
settings.car_model_index = app->selected_model->index;
|
||||
@@ -570,6 +294,7 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
//Free the Model.
|
||||
free(app->selected_model);
|
||||
app->selected_model = NULL;
|
||||
#endif
|
||||
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
@@ -645,15 +370,14 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
int32_t protopirate_app(char* p) {
|
||||
//Stop charging while running the app.
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
ProtoPirateApp* protopirate_app = protopirate_app_alloc();
|
||||
if(!protopirate_app) {
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Stop charging while running the app.
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
// Handle Command line PSF that may have been passed to us
|
||||
bool load_saved = (p && strlen(p));
|
||||
if(load_saved) {
|
||||
@@ -683,6 +407,8 @@ int32_t protopirate_app(char* p) {
|
||||
|
||||
//Free the App and allow chargin again.
|
||||
protopirate_app_free(protopirate_app);
|
||||
|
||||
//Restore Charging State
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
return 0;
|
||||
}
|
||||
+7
-44
@@ -35,25 +35,19 @@
|
||||
#include "scenes/plugins/protopirate_about_plugin.h"
|
||||
#include "scenes/plugins/protopirate_psa_bf_plugin.h"
|
||||
#include "scenes/plugins/protopirate_tool_scene_plugin.h"
|
||||
#include "helpers/protopirate_plugins.h"
|
||||
#include "helpers/protopirate_views.h"
|
||||
#include "helpers/protopirate_radio.h"
|
||||
#include "helpers/protopirate_protocol_plugin_host.h"
|
||||
#include "helpers/protopirate_txrx.h"
|
||||
#include "helpers/protopirate_models.h"
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include "helpers/protopirate_settings.h"
|
||||
|
||||
#define CONFIG_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_config.fal")
|
||||
#define SAVED_INFO_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_saved_info.fal")
|
||||
#define ABOUT_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_about.fal")
|
||||
#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_emulate.fal")
|
||||
#define SUB_DECODE_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_sub_decode.fal")
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
#define TIMING_TUNER_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_timing_tuner.fal")
|
||||
#endif
|
||||
#define PSA_BF_PLUGIN_PATH APP_ASSETS_PATH("plugins/pp_bf.fal")
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
#define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("keystore/encrypted")
|
||||
#else
|
||||
#define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted")
|
||||
#endif
|
||||
|
||||
typedef struct VariableItemList VariableItemList;
|
||||
|
||||
@@ -110,9 +104,6 @@ struct ProtoPirateApp {
|
||||
uint16_t save_history_idx;
|
||||
FlipperApplication* plugin_flipper_application;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define EMULATE_NAV_NONE 0U
|
||||
#define EMULATE_NAV_POP 1U
|
||||
#define EMULATE_NAV_STOP_APP 2U
|
||||
const ProtoPirateEmulatePlugin* emulate_plugin;
|
||||
uint8_t emulate_nav_pending;
|
||||
#endif
|
||||
@@ -124,15 +115,10 @@ struct ProtoPirateApp {
|
||||
FlipperApplication* tool_scene_plugin_flipper_application;
|
||||
const ProtoPirateToolScenePlugin* tool_scene_plugin;
|
||||
ProtoPirateToolScenePluginKind tool_scene_plugin_kind;
|
||||
#define TOOL_SCENE_NAV_NONE 0U
|
||||
#define TOOL_SCENE_NAV_POP 1U
|
||||
#define TOOL_SCENE_NAV_NEXT 2U
|
||||
#define TOOL_SCENE_NAV_SEARCH_PREVIOUS 3U
|
||||
uint8_t tool_scene_nav_pending;
|
||||
uint32_t tool_scene_nav_target;
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
ProtoPirateCarModel* selected_model;
|
||||
uint16_t car_models_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
@@ -148,29 +134,6 @@ bool protopirate_tool_scene_on_enter(void* app, ProtoPirateToolScenePluginKind k
|
||||
bool protopirate_tool_scene_on_event(void* app, SceneManagerEvent event);
|
||||
void protopirate_tool_scene_on_exit(void* app);
|
||||
void protopirate_tool_scene_plugin_release(ProtoPirateApp* app);
|
||||
|
||||
typedef enum ProtoPirateSharedPlugin {
|
||||
ProtoPirateSharedPluginsConfig,
|
||||
ProtoPirateSharedPluginsSavedInfo,
|
||||
ProtoPirateSharedPluginsAbout,
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ProtoPirateSharedPluginsEmulate,
|
||||
#endif
|
||||
ProtoPirateSharedPluginsToolScene,
|
||||
ProtoPirateSharedPluginsSubDecode,
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
ProtoPirateSharedPluginsTimingTuner,
|
||||
#endif
|
||||
ProtoPirateSharedPluginsPSABruteforce,
|
||||
ProtoPirateSharedPluginsTXRX,
|
||||
} ProtoPirateSharedPlugin;
|
||||
|
||||
bool shared_plugin_load(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateSharedPlugin plugin_type,
|
||||
const char* txrx_path);
|
||||
void shared_plugin_unload(ProtoPirateApp* app, ProtoPirateSharedPlugin plugin_type);
|
||||
|
||||
void protopirate_app_free(ProtoPirateApp* app);
|
||||
|
||||
static const NotificationSequence sequence_tx = {
|
||||
|
||||
@@ -204,10 +204,6 @@ void protopirate_history_format_status_text(
|
||||
furi_check(instance);
|
||||
furi_check(output);
|
||||
|
||||
if(output_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t n = protopirate_history_get_item(instance);
|
||||
if(n >= PROTOPIRATE_HISTORY_MAX) {
|
||||
snprintf(output, output_size, "FULL");
|
||||
@@ -216,15 +212,6 @@ void protopirate_history_format_status_text(
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_history_get_status_text(ProtoPirateHistory* instance, FuriString* output) {
|
||||
furi_check(instance);
|
||||
furi_check(output);
|
||||
|
||||
char status_text[16];
|
||||
protopirate_history_format_status_text(instance, status_text, sizeof(status_text));
|
||||
furi_string_set_str(output, status_text);
|
||||
}
|
||||
|
||||
bool protopirate_history_get_capture_path(
|
||||
ProtoPirateHistory* instance,
|
||||
uint16_t idx,
|
||||
|
||||
@@ -19,7 +19,6 @@ void protopirate_history_format_status_text(
|
||||
ProtoPirateHistory* instance,
|
||||
char* output,
|
||||
size_t output_size);
|
||||
void protopirate_history_get_status_text(ProtoPirateHistory* instance, FuriString* output);
|
||||
|
||||
bool protopirate_history_get_capture_path(
|
||||
ProtoPirateHistory* instance,
|
||||
|
||||
@@ -131,10 +131,10 @@ static void protopirate_scene_receiver_config_set_hopping_running(VariableItem*
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
subghz_setting_get_frequency_default_index(app->setting));
|
||||
}
|
||||
|
||||
app->txrx->hopper_state = hopping_value[index];
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
static void protopirate_scene_receiver_config_set_model(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
uint8_t direction = variable_item_get_current_value_index(item);
|
||||
@@ -238,6 +238,7 @@ static void protopirate_scene_receiver_config_set_model(VariableItem* item) {
|
||||
variable_item_set_locked(hop_menu, lock, "Turn off\nCar Model\nto do that!");
|
||||
variable_item_set_locked(preset_menu, lock, "Turn off\nCar Model\nto do that!");
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
protopirate_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
|
||||
@@ -279,13 +280,13 @@ static uint8_t protopirate_scene_receiver_config_hopper_value_index(
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(value == values[0]) {
|
||||
return 0;
|
||||
return false;
|
||||
} else {
|
||||
variable_item_set_current_value_text(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
" -----");
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,20 +340,20 @@ static void
|
||||
FURI_LOG_D("TEST", "Index= %lu", index);
|
||||
|
||||
switch(index) {
|
||||
case ProtoPirateSettingIndexCarModel: {
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
case ProtoPirateSettingIndexCarModel:
|
||||
//Reset the Models Menu
|
||||
VariableItem* model_menu =
|
||||
variable_item_list_get(app->variable_item_list, ProtoPirateSettingIndexCarModel);
|
||||
variable_item_set_current_value_index(model_menu, 0);
|
||||
protopirate_scene_receiver_config_set_model(model_menu);
|
||||
break;
|
||||
}
|
||||
case ProtoPirateSettingIndexLock: {
|
||||
#endif
|
||||
case ProtoPirateSettingIndexLock:
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSceneSettingLock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void plugin_on_enter(void* context, bool show_lock_keyboard) {
|
||||
@@ -367,12 +368,14 @@ static void plugin_on_enter(void* context, bool show_lock_keyboard) {
|
||||
}
|
||||
|
||||
//Add he car model the list, with the correct selection and text.
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
app->selected_model->name,
|
||||
0, //Plus NONE
|
||||
protopirate_scene_receiver_config_set_model,
|
||||
app);
|
||||
#endif
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
@@ -393,10 +396,12 @@ static void plugin_on_enter(void* context, bool show_lock_keyboard) {
|
||||
subghz_setting_get_frequency(app->setting, value_index) / 1000000,
|
||||
(subghz_setting_get_frequency(app->setting, value_index) % 1000000) / 10000);
|
||||
variable_item_set_current_value_text(item, text_buf);
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
variable_item_set_locked(
|
||||
item,
|
||||
app->selected_model && (app->selected_model->index),
|
||||
"Turn off\nCar Model\nto do that!");
|
||||
#endif
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
@@ -408,10 +413,12 @@ static void plugin_on_enter(void* context, bool show_lock_keyboard) {
|
||||
app->txrx->hopper_state, hopping_value, ON_OFF_COUNT, app);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, on_off_text[value_index]);
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
variable_item_set_locked(
|
||||
item,
|
||||
app->selected_model && (app->selected_model->index),
|
||||
"Turn off\nCar Model\nto do that!");
|
||||
#endif
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
@@ -424,10 +431,12 @@ static void plugin_on_enter(void* context, bool show_lock_keyboard) {
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(
|
||||
item, subghz_setting_get_preset_name(app->setting, value_index));
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
variable_item_set_locked(
|
||||
item,
|
||||
app->selected_model && (app->selected_model->index),
|
||||
"Turn off\nCar Model\nto do that!");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
// TX power option
|
||||
@@ -495,8 +504,10 @@ void config_plugin_set_host_api(const ProtoPirateConfigSceneHostApi* host_api) {
|
||||
|
||||
static const ProtoPirateConfigPlugin protopirate_config_plugin = {
|
||||
.plugin_name = "Config",
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
.car_model_get_by_index = car_model_get_by_index,
|
||||
.car_model_get_count = car_model_get_count,
|
||||
#endif
|
||||
.on_enter = plugin_on_enter,
|
||||
.set_host_api = config_plugin_set_host_api,
|
||||
};
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
#include "../../protopirate_app_i.h"
|
||||
#include "helpers/protopirate_models.h"
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
#include "helpers/variable_item_list.h"
|
||||
|
||||
#define PROTOPIRATE_CONFIG_PLUGIN_APP_ID "pp_config"
|
||||
#define PROTOPIRATE_CONFIG_PLUGIN_API_VERSION 2U
|
||||
|
||||
enum ProtoPirateSettingIndex {
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
ProtoPirateSettingIndexCarModel,
|
||||
#endif
|
||||
ProtoPirateSettingIndexFrequency,
|
||||
ProtoPirateSettingIndexHopping,
|
||||
ProtoPirateSettingIndexModulation,
|
||||
@@ -35,12 +38,14 @@ typedef struct ProtoPirateConfigSceneHostApi {
|
||||
|
||||
typedef struct ProtoPirateConfigPlugin {
|
||||
const char* plugin_name;
|
||||
#ifdef ENABLE_MODELS_DATABASE
|
||||
bool (*car_model_get_by_index)(
|
||||
ProtoPirateCarModel* car_model,
|
||||
uint16_t index,
|
||||
uint16_t model_count,
|
||||
SubGhzSetting* app_settings);
|
||||
uint16_t (*car_model_get_count)(void);
|
||||
#endif
|
||||
void (*on_enter)(void* app, bool show_lock_keyboard);
|
||||
void (*set_host_api)(const ProtoPirateConfigSceneHostApi* host_api);
|
||||
} ProtoPirateConfigPlugin;
|
||||
@@ -179,18 +179,6 @@ static bool emulate_hitag2_recovered_yes(FlipperFormat* flipper_format) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void emulate_request_nav_pop(ProtoPirateApp* app) {
|
||||
app->emulate_nav_pending = EMULATE_NAV_POP;
|
||||
}
|
||||
|
||||
static void emulate_request_nav_after_exit(ProtoPirateApp* app) {
|
||||
if(scene_manager_has_previous_scene(app->scene_manager, ProtoPirateSceneStart)) {
|
||||
app->emulate_nav_pending = EMULATE_NAV_POP;
|
||||
} else {
|
||||
app->emulate_nav_pending = EMULATE_NAV_STOP_APP;
|
||||
}
|
||||
}
|
||||
|
||||
static bool emulate_prompt_hitag2_key(ProtoPirateApp* app, EmulateContext* ctx);
|
||||
|
||||
static void emulate_hitag2_key_input_callback(void* context) {
|
||||
@@ -211,7 +199,8 @@ static void emulate_hitag2_key_input_callback(void* context) {
|
||||
|
||||
if(!emulate_write_hitag2_key(ctx->flipper_format, key)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1080,7 +1069,8 @@ static void plugin_on_enter(void* context) {
|
||||
|
||||
if(!g_host_api->ensure_view_about || !g_host_api->ensure_view_about(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1101,7 +1091,8 @@ static void plugin_on_enter(void* context) {
|
||||
if(!g_host_api->radio_init || !g_host_api->radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for emulate scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1109,14 +1100,16 @@ static void plugin_on_enter(void* context) {
|
||||
if(!emulate_radio_ready(app)) {
|
||||
FURI_LOG_E(TAG, "Radio still incomplete after emulate init");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
emulate_context = malloc(sizeof(EmulateContext));
|
||||
if(!emulate_context) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate emulate context");
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
memset(emulate_context, 0, sizeof(EmulateContext));
|
||||
@@ -1126,7 +1119,8 @@ static void plugin_on_enter(void* context) {
|
||||
if(!ctx->protocol_name) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate protocol name string");
|
||||
emulate_context_free();
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1134,7 +1128,8 @@ static void plugin_on_enter(void* context) {
|
||||
FURI_LOG_E(TAG, "No file path set");
|
||||
emulate_context_free();
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1143,7 +1138,8 @@ static void plugin_on_enter(void* context) {
|
||||
FURI_LOG_E(TAG, "Failed to open storage");
|
||||
emulate_context_free();
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1148,8 @@ static void plugin_on_enter(void* context) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate FlipperFormat");
|
||||
emulate_context_free();
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1160,7 +1157,8 @@ static void plugin_on_enter(void* context) {
|
||||
FURI_LOG_E(TAG, "Failed to open file: %s", app->loaded_file_path);
|
||||
emulate_context_free();
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1313,7 +1311,8 @@ static void plugin_on_enter(void* context) {
|
||||
FURI_LOG_E(TAG, "Failed to show HITAG2 key input");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
emulate_context_free();
|
||||
emulate_request_nav_pop(app);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1474,7 +1473,13 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
emulate_request_nav_after_exit(app);
|
||||
if(!scene_manager_has_previous_scene(app->scene_manager, ProtoPirateSceneStart)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateStopApp);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#define PROTOPIRATE_EMULATE_PLUGIN_APP_ID "pp_emulate"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/widget_elements/widget_element.h>
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
#ifdef PROTOPIRATE_PSA_BF_PLUGIN_BUILD
|
||||
#include "pp_bf_icons.h"
|
||||
#else
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
|
||||
@@ -47,8 +47,12 @@ void plugin_protopirate_scene_saved_info_on_enter(void* context) {
|
||||
|
||||
if(!g_saved_info_scene_host_api->ensure_widget(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSavedInfoExit);
|
||||
if(!scene_manager_has_previous_scene(app->scene_manager, ProtoPirateSceneStart)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateStopApp);
|
||||
} else
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -285,9 +289,16 @@ bool plugin_protopirate_scene_saved_info_on_event(void* context, SceneManagerEve
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
return (
|
||||
app->psa_bf_plugin && app->psa_bf_plugin->is_running &&
|
||||
app->psa_bf_plugin->on_scene_event(app, ProtoPiratePsaBfContextReceiverInfo, event));
|
||||
if(app->psa_bf_plugin && app->psa_bf_plugin->is_running &&
|
||||
app->psa_bf_plugin->on_scene_event(app, ProtoPiratePsaBfContextReceiverInfo, event)) {
|
||||
consumed = true;
|
||||
} else {
|
||||
if(!scene_manager_has_previous_scene(app->scene_manager, ProtoPirateSceneStart)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateStopApp);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSavedInfoDelete) {
|
||||
FURI_LOG_I(TAG, "Delete requested");
|
||||
@@ -312,8 +323,13 @@ bool plugin_protopirate_scene_saved_info_on_event(void* context, SceneManagerEve
|
||||
g_saved_info_scene_host_api->storage_delete_file(app->loaded_file_path);
|
||||
notification_message(app->notifications, &sequence_semi_success);
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSavedInfoExit);
|
||||
if(!scene_manager_has_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateStopApp);
|
||||
} else
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
@@ -336,7 +352,7 @@ bool plugin_protopirate_scene_saved_info_on_event(void* context, SceneManagerEve
|
||||
|
||||
//Send custom event back to the scene, so it can start emulate for us and avoid the crashes.
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSavedInfoEmulateDelayedStart);
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateEmulate);
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
|
||||
#include "../../defines.h"
|
||||
@@ -58,9 +57,13 @@ typedef struct {
|
||||
void (*receiver_add_data_statusbar)(
|
||||
ProtoPirateReceiver* receiver,
|
||||
const char* frequency_str,
|
||||
size_t frequency_size,
|
||||
const char* preset_str,
|
||||
size_t preset_size,
|
||||
const char* history_stat_str,
|
||||
size_t history_stat_size,
|
||||
bool external_radio);
|
||||
|
||||
uint16_t (*receiver_get_idx_menu)(ProtoPirateReceiver* receiver);
|
||||
void (*receiver_set_idx_menu)(ProtoPirateReceiver* receiver, uint16_t idx);
|
||||
void (*receiver_set_callback)(
|
||||
|
||||
@@ -12,7 +12,11 @@ static const ProtoPirateAboutSceneHostApi protopirate_about_scene_host_api = {
|
||||
void protopirate_scene_about_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(!shared_plugin_load(app, ProtoPirateSharedPluginsAbout, NULL)) {
|
||||
if(!shared_plugin_load(
|
||||
(void**)&app->plugin_flipper_application,
|
||||
(const void**)&app->about_plugin,
|
||||
ProtoPirateSharedPluginsAbout,
|
||||
NULL)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -40,5 +44,6 @@ void protopirate_scene_about_on_exit(void* context) {
|
||||
view_set_draw_callback(app->view_about, NULL);
|
||||
view_set_input_callback(app->view_about, NULL);
|
||||
view_set_context(app->view_about, NULL);
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsAbout);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->plugin_flipper_application, (const void**)&app->about_plugin);
|
||||
}
|
||||
@@ -7,8 +7,6 @@
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "../protopirate_history.h"
|
||||
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
|
||||
#define TAG "PPSceneEmulate"
|
||||
|
||||
static bool host_radio_init(void* app) {
|
||||
@@ -53,24 +51,6 @@ static void host_storage_delete_temp(void) {
|
||||
protopirate_storage_delete_temp();
|
||||
}
|
||||
|
||||
static void protopirate_emulate_apply_pending_nav(ProtoPirateApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
const uint8_t nav = app->emulate_nav_pending;
|
||||
if(nav == EMULATE_NAV_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
app->emulate_nav_pending = EMULATE_NAV_NONE;
|
||||
|
||||
if(nav == EMULATE_NAV_POP) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
} else if(nav == EMULATE_NAV_STOP_APP) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
static const ProtoPirateEmulateHostApi protopirate_emulate_host_api = {
|
||||
.radio_init = host_radio_init,
|
||||
.apply_protocol_registry_for_context = host_apply_protocol_registry_for_context,
|
||||
@@ -86,15 +66,18 @@ void protopirate_emulate_context_release(ProtoPirateApp* app) {
|
||||
if(app->emulate_plugin && app->emulate_plugin->context_release) {
|
||||
app->emulate_plugin->context_release(app);
|
||||
}
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsEmulate);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->plugin_flipper_application, (const void**)&app->emulate_plugin);
|
||||
}
|
||||
|
||||
void protopirate_scene_emulate_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
app->emulate_nav_pending = EMULATE_NAV_NONE;
|
||||
|
||||
if(!shared_plugin_load(app, ProtoPirateSharedPluginsEmulate, NULL)) {
|
||||
if(!shared_plugin_load(
|
||||
(void**)&app->plugin_flipper_application,
|
||||
(const void**)&app->emulate_plugin,
|
||||
ProtoPirateSharedPluginsEmulate,
|
||||
NULL)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -103,18 +86,19 @@ void protopirate_scene_emulate_on_enter(void* context) {
|
||||
}
|
||||
|
||||
app->emulate_plugin->on_enter(app);
|
||||
protopirate_emulate_apply_pending_nav(app);
|
||||
}
|
||||
|
||||
bool protopirate_scene_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(!app->emulate_plugin || !app->emulate_plugin->on_event) {
|
||||
return false;
|
||||
bool consumed = false;
|
||||
//Handle Saved event in plugin.
|
||||
if(app->emulate_plugin && app->emulate_plugin->on_event(app, event)) {
|
||||
consumed = true;
|
||||
} else {
|
||||
consumed = shared_plugin_handle_navigation_events(
|
||||
app->scene_manager, app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
const bool consumed = app->emulate_plugin->on_event(app, event);
|
||||
protopirate_emulate_apply_pending_nav(app);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ static void protopirate_scene_receiver_update_statusbar(void* context) {
|
||||
char modulation_str[8] = {0};
|
||||
char history_stat_str[16] = {0};
|
||||
|
||||
protopirate_get_frequency_modulation_str(
|
||||
app, frequency_str, sizeof(frequency_str), modulation_str, sizeof(modulation_str));
|
||||
protopirate_get_frequency_modulation_str(app, frequency_str, 16, modulation_str, 8);
|
||||
|
||||
bool is_external = false;
|
||||
if(app->radio_initialized && app->txrx->radio_device) {
|
||||
@@ -33,14 +32,20 @@ static void protopirate_scene_receiver_update_statusbar(void* context) {
|
||||
}
|
||||
|
||||
if(app->txrx->history) {
|
||||
protopirate_history_format_status_text(
|
||||
app->txrx->history, history_stat_str, sizeof(history_stat_str));
|
||||
protopirate_history_format_status_text(app->txrx->history, history_stat_str, 20);
|
||||
} else {
|
||||
snprintf(history_stat_str, sizeof(history_stat_str), "0/%u", PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(history_stat_str, 16, "0/%u", PROTOPIRATE_HISTORY_MAX);
|
||||
}
|
||||
|
||||
protopirate_view_receiver_add_data_statusbar(
|
||||
app->protopirate_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
app->protopirate_receiver,
|
||||
frequency_str,
|
||||
16,
|
||||
modulation_str,
|
||||
8,
|
||||
history_stat_str,
|
||||
16,
|
||||
is_external);
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_callback(
|
||||
|
||||
@@ -11,7 +11,11 @@ static const ProtoPirateConfigSceneHostApi protopirate_config_scene_host_api = {
|
||||
void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(!shared_plugin_load(app, ProtoPirateSharedPluginsConfig, NULL)) {
|
||||
if(!shared_plugin_load(
|
||||
(void**)&app->plugin_flipper_application,
|
||||
(const void**)&app->config_plugin,
|
||||
ProtoPirateSharedPluginsConfig,
|
||||
NULL)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -39,6 +43,6 @@ bool protopirate_scene_receiver_config_on_event(void* context, SceneManagerEvent
|
||||
|
||||
void protopirate_scene_receiver_config_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsConfig);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->plugin_flipper_application, (const void**)&app->config_plugin);
|
||||
}
|
||||
@@ -16,7 +16,11 @@ static const ProtoPirateSavedInfoSceneHostApi protopirate_saved_info_scene_host_
|
||||
void protopirate_scene_saved_info_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
if(!shared_plugin_load(app, ProtoPirateSharedPluginsSavedInfo, NULL)) {
|
||||
if(!shared_plugin_load(
|
||||
(void**)&app->plugin_flipper_application,
|
||||
(const void**)&app->saved_info_plugin,
|
||||
ProtoPirateSharedPluginsSavedInfo,
|
||||
NULL)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -29,26 +33,18 @@ void protopirate_scene_saved_info_on_enter(void* context) {
|
||||
bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = ((ProtoPirateApp*)context);
|
||||
|
||||
//I can't set the next scene from inside the plugin, or it causes crazy crashes.
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSavedInfoEmulateDelayedStart) {
|
||||
//Start Emulate Scene.
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneEmulate);
|
||||
return true;
|
||||
#endif
|
||||
} else if(event.event == ProtoPirateCustomEventSavedInfoExit) {
|
||||
scene_manager_previous_scene(((ProtoPirateApp*)context)->scene_manager);
|
||||
return true;
|
||||
}
|
||||
//Handle event in plugin.
|
||||
if(app->saved_info_plugin->on_event(app, event)) {
|
||||
return true;
|
||||
} else {
|
||||
return shared_plugin_handle_navigation_events(
|
||||
app->scene_manager, app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
//Handle Saved Info event in plugin.
|
||||
return app->saved_info_plugin->on_event(app, event);
|
||||
}
|
||||
|
||||
void protopirate_scene_saved_info_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
shared_plugin_unload(app, ProtoPirateSharedPluginsSavedInfo);
|
||||
shared_plugin_unload(
|
||||
(void**)&app->plugin_flipper_application, (const void**)&app->saved_info_plugin);
|
||||
}
|
||||
@@ -92,7 +92,6 @@ bool protopirate_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneStart, event.event);
|
||||
FURI_LOG_I(TAG, "Suppressing Charging While in a scene.");
|
||||
if(event.event == SubmenuIndexProtoPirateAbout) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneAbout);
|
||||
consumed = true;
|
||||
@@ -128,7 +127,6 @@ bool protopirate_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void protopirate_scene_start_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
@@ -12,17 +12,13 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
}
|
||||
|
||||
bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSubDecodeEmulateDelayedStart) {
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
scene_manager_next_scene(
|
||||
((ProtoPirateApp*)context)->scene_manager, ProtoPirateSceneEmulate);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
ProtoPirateApp* app = (ProtoPirateApp*)context;
|
||||
if(protopirate_tool_scene_on_event(context, event)) {
|
||||
return true;
|
||||
} else {
|
||||
return shared_plugin_handle_navigation_events(
|
||||
app->scene_manager, app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
return protopirate_tool_scene_on_event(context, event);
|
||||
}
|
||||
|
||||
void protopirate_scene_sub_decode_on_exit(void* context) {
|
||||
@@ -74,10 +70,26 @@ static const ProtoPirateToolSceneHostApi* g_tool_scene_host_api = NULL;
|
||||
app, frequency, frequency_size, modulation, modulation_size)
|
||||
#define radio_device_loader_is_external(radio_device) \
|
||||
g_tool_scene_host_api->radio_device_is_external(radio_device)
|
||||
|
||||
#define protopirate_view_receiver_add_data_statusbar( \
|
||||
receiver, frequency, modulation, history, external) \
|
||||
receiver, \
|
||||
frequency, \
|
||||
frequency_size, \
|
||||
modulation, \
|
||||
modulation_size, \
|
||||
history, \
|
||||
history_size, \
|
||||
external) \
|
||||
g_tool_scene_host_api->receiver_add_data_statusbar( \
|
||||
receiver, frequency, modulation, history, external)
|
||||
receiver, \
|
||||
frequency, \
|
||||
frequency_size, \
|
||||
modulation, \
|
||||
modulation_size, \
|
||||
history, \
|
||||
history_size, \
|
||||
external)
|
||||
|
||||
#define protopirate_view_receiver_get_idx_menu(receiver) \
|
||||
g_tool_scene_host_api->receiver_get_idx_menu(receiver)
|
||||
#define protopirate_view_receiver_set_idx_menu(receiver, idx) \
|
||||
@@ -231,12 +243,11 @@ static void protopirate_scene_sub_decode_update_receiver_statusbar(
|
||||
char modulation_str[8] = {0};
|
||||
char history_stat_str[16] = {0};
|
||||
|
||||
protopirate_get_frequency_modulation_str(
|
||||
app, frequency_str, sizeof(frequency_str), modulation_str, sizeof(modulation_str));
|
||||
protopirate_get_frequency_modulation_str(app, frequency_str, 16, modulation_str, 8);
|
||||
if(ctx && ctx->frequency > 0U) {
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
20,
|
||||
"%03lu.%02lu",
|
||||
(unsigned long)((ctx->frequency / 1000000UL) % 1000UL),
|
||||
(unsigned long)((ctx->frequency / 10000UL) % 100UL));
|
||||
@@ -244,13 +255,20 @@ static void protopirate_scene_sub_decode_update_receiver_statusbar(
|
||||
|
||||
const uint16_t signal_count =
|
||||
(ctx && ctx->history) ? protopirate_history_get_item(ctx->history) : 0U;
|
||||
snprintf(
|
||||
history_stat_str, sizeof(history_stat_str), "%u/%u", signal_count, PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(history_stat_str, 16, "%u/%u", signal_count, PROTOPIRATE_HISTORY_MAX);
|
||||
|
||||
bool is_external =
|
||||
app->txrx->radio_device ? radio_device_loader_is_external(app->txrx->radio_device) : false;
|
||||
|
||||
protopirate_view_receiver_add_data_statusbar(
|
||||
app->protopirate_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
app->protopirate_receiver,
|
||||
frequency_str,
|
||||
16,
|
||||
modulation_str,
|
||||
8,
|
||||
history_stat_str,
|
||||
16,
|
||||
is_external);
|
||||
}
|
||||
|
||||
static void protopirate_scene_sub_decode_update_receiver_progress(
|
||||
@@ -523,14 +541,16 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
|
||||
if(!protopirate_ensure_receiver_view(app) || !protopirate_ensure_widget(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!app->radio_initialized && !protopirate_radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for sub decode scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -542,7 +562,8 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
if(!app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate receiver for sub decode scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -551,7 +572,8 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
g_decode_ctx = malloc(sizeof(SubDecodeContext));
|
||||
if(!g_decode_ctx) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate decode context");
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
memset(g_decode_ctx, 0, sizeof(SubDecodeContext));
|
||||
@@ -579,7 +601,8 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
free(g_decode_ctx);
|
||||
g_decode_ctx = NULL;
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
owns_history = true;
|
||||
@@ -607,17 +630,17 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
g_decode_ctx->state = DecodeStateOpenFile;
|
||||
protopirate_scene_sub_decode_prepare_receiver_view(app);
|
||||
} else {
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool consumed = false;
|
||||
SubDecodeContext* ctx = g_decode_ctx;
|
||||
|
||||
if(!ctx) return false;
|
||||
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSubDecodeUpdate) {
|
||||
// Update receiver view with new history items (when signals are detected during decoding)
|
||||
@@ -786,7 +809,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
FURI_LOG_I(TAG, "Emulate from sub-decode temp file: %s", app->loaded_file_path);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeEmulateDelayedStart);
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateEmulate);
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
TAG, "Failed to prepare emulate capture %u", ctx->selected_history_index);
|
||||
@@ -836,8 +859,8 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
if(!protopirate_scene_sub_decode_open_browser_for_next_file(app)) {
|
||||
protopirate_history_reset(ctx->history);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_SEARCH_PREVIOUS;
|
||||
app->tool_scene_nav_target = ProtoPirateSceneStart;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
@@ -1420,7 +1443,6 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
}
|
||||
// If in history view, back is handled by ViewReceiverBack event
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// scenes/protopirate_scene_timing_tuner.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
#ifndef PROTOPIRATE_TIMING_TUNER_PLUGIN_BUILD
|
||||
|
||||
void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
@@ -9,7 +9,13 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
}
|
||||
|
||||
bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent event) {
|
||||
return protopirate_tool_scene_on_event(context, event);
|
||||
ProtoPirateApp* app = (ProtoPirateApp*)context;
|
||||
if(protopirate_tool_scene_on_event(context, event)) {
|
||||
return true;
|
||||
} else {
|
||||
return shared_plugin_handle_navigation_events(
|
||||
app->scene_manager, app->view_dispatcher, event);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_timing_tuner_on_exit(void* context) {
|
||||
@@ -651,14 +657,16 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
|
||||
if(!protopirate_ensure_view_about(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!app->radio_initialized && !protopirate_radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for timing tuner");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -670,7 +678,8 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
if(!app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate receiver for timing tuner");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -678,7 +687,8 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
if(!g_timing_ctx) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate timing tuner context");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
memset(g_timing_ctx, 0, sizeof(TimingTunerContext));
|
||||
@@ -706,7 +716,8 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
view_set_input_callback(app->view_about, NULL);
|
||||
timing_tuner_context_free();
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
return;
|
||||
}
|
||||
// Set up worker callbacks
|
||||
@@ -738,19 +749,20 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
|
||||
bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == 0) {
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_POP;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateBack);
|
||||
consumed = true;
|
||||
} else if(event.event == 1) {
|
||||
if(g_timing_ctx && g_timing_ctx->is_receiving) {
|
||||
protopirate_rx_end(app);
|
||||
g_timing_ctx->is_receiving = false;
|
||||
}
|
||||
app->tool_scene_nav_pending = TOOL_SCENE_NAV_NEXT;
|
||||
app->tool_scene_nav_target = ProtoPirateSceneReceiverConfig;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventPluginNavigateConfig);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
|
||||
@@ -27,9 +27,9 @@ typedef struct {
|
||||
uint8_t history_item;
|
||||
float rssi;
|
||||
bool auto_save;
|
||||
FuriString* frequency_str;
|
||||
FuriString* preset_str;
|
||||
FuriString* history_stat_str;
|
||||
char* frequency_str;
|
||||
char* preset_str;
|
||||
char* history_stat_str;
|
||||
FuriString* draw_scratch;
|
||||
bool external_radio;
|
||||
ProtoPirateLock lock;
|
||||
@@ -191,24 +191,26 @@ static void protopirate_view_receiver_update_offset(ProtoPirateReceiver* receive
|
||||
void protopirate_view_receiver_add_data_statusbar(
|
||||
ProtoPirateReceiver* receiver,
|
||||
const char* frequency_str,
|
||||
size_t freqency_size,
|
||||
const char* preset_str,
|
||||
size_t preset_size,
|
||||
const char* history_stat_str,
|
||||
size_t history_stat_size,
|
||||
bool external_radio) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
{
|
||||
furi_string_set_str(model->frequency_str, frequency_str);
|
||||
furi_string_set_str(model->preset_str, preset_str);
|
||||
furi_string_set_str(model->history_stat_str, history_stat_str);
|
||||
memcpy(model->frequency_str, frequency_str, freqency_size);
|
||||
memcpy(model->preset_str, preset_str, preset_size);
|
||||
memcpy(model->history_stat_str, history_stat_str, history_stat_size);
|
||||
model->external_radio = external_radio;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static void protopirate_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
||||
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
@@ -280,6 +282,9 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
canvas, 4, 9 + (i * FRAME_HEIGHT), furi_string_get_cstr(model->draw_scratch));
|
||||
}
|
||||
|
||||
//Last item may be selected, it wont reset.
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
//Draw scrollbar if needed
|
||||
if(scrollbar) {
|
||||
// Calculate maximum scroll position
|
||||
@@ -360,8 +365,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->sub_decode_mode) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 127, 0, AlignRight, AlignTop, furi_string_get_cstr(model->preset_str));
|
||||
canvas_draw_str_aligned(canvas, 127, 0, AlignRight, AlignTop, model->preset_str);
|
||||
} else {
|
||||
if(model->external_radio) {
|
||||
canvas_draw_str_aligned(canvas, 127, 0, AlignRight, AlignTop, "Ext");
|
||||
@@ -381,12 +385,12 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
//Draw the unlock instructions last, so they appear on top...
|
||||
if(model->lock_count) {
|
||||
if(model->sub_decode_mode) {
|
||||
canvas_draw_str(canvas, 44, 63, furi_string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 96, 63, furi_string_get_cstr(model->history_stat_str));
|
||||
canvas_draw_str(canvas, 44, 63, model->frequency_str);
|
||||
canvas_draw_str(canvas, 96, 63, model->history_stat_str);
|
||||
} else {
|
||||
canvas_draw_str(canvas, 44, 63, furi_string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 79, 63, furi_string_get_cstr(model->preset_str));
|
||||
canvas_draw_str(canvas, 96, 63, furi_string_get_cstr(model->history_stat_str));
|
||||
canvas_draw_str(canvas, 44, 63, model->frequency_str);
|
||||
canvas_draw_str(canvas, 79, 63, model->preset_str);
|
||||
canvas_draw_str(canvas, 96, 63, model->history_stat_str);
|
||||
}
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_bold_rounded_frame(canvas, 14, 8, 99, 48);
|
||||
@@ -402,12 +406,12 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
canvas_draw_str(canvas, 74, 62, "Locked");
|
||||
} else {
|
||||
if(model->sub_decode_mode) {
|
||||
canvas_draw_str(canvas, 44, 63, furi_string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 96, 63, furi_string_get_cstr(model->history_stat_str));
|
||||
canvas_draw_str(canvas, 44, 63, model->frequency_str);
|
||||
canvas_draw_str(canvas, 96, 63, model->history_stat_str);
|
||||
} else {
|
||||
canvas_draw_str(canvas, 44, 63, furi_string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 79, 63, furi_string_get_cstr(model->preset_str));
|
||||
canvas_draw_str(canvas, 96, 63, furi_string_get_cstr(model->history_stat_str));
|
||||
canvas_draw_str(canvas, 44, 63, model->frequency_str);
|
||||
canvas_draw_str(canvas, 79, 63, model->preset_str);
|
||||
canvas_draw_str(canvas, 96, 63, model->history_stat_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,9 +587,9 @@ ProtoPirateReceiver* protopirate_view_receiver_alloc(bool auto_save) {
|
||||
ProtoPirateReceiverModel * model,
|
||||
{
|
||||
model->history = NULL;
|
||||
model->frequency_str = furi_string_alloc();
|
||||
model->preset_str = furi_string_alloc();
|
||||
model->history_stat_str = furi_string_alloc();
|
||||
model->frequency_str = malloc(16);
|
||||
model->preset_str = malloc(8);
|
||||
model->history_stat_str = malloc(16);
|
||||
model->draw_scratch = furi_string_alloc();
|
||||
furi_check(model->draw_scratch);
|
||||
model->list_offset = 0;
|
||||
@@ -612,9 +616,9 @@ void protopirate_view_receiver_free(ProtoPirateReceiver* receiver) {
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
{
|
||||
furi_string_free(model->frequency_str);
|
||||
furi_string_free(model->preset_str);
|
||||
furi_string_free(model->history_stat_str);
|
||||
free(model->frequency_str);
|
||||
free(model->preset_str);
|
||||
free(model->history_stat_str);
|
||||
furi_string_free(model->draw_scratch);
|
||||
},
|
||||
false);
|
||||
|
||||
@@ -21,8 +21,11 @@ View* protopirate_view_receiver_get_view(ProtoPirateReceiver* receiver);
|
||||
void protopirate_view_receiver_add_data_statusbar(
|
||||
ProtoPirateReceiver* receiver,
|
||||
const char* frequency_str,
|
||||
size_t freqency_size,
|
||||
const char* preset_str,
|
||||
size_t preset_size,
|
||||
const char* history_stat_str,
|
||||
size_t history_stat_size,
|
||||
bool external_radio);
|
||||
|
||||
uint16_t protopirate_view_receiver_get_idx_menu(ProtoPirateReceiver* receiver);
|
||||
|
||||
Reference in new issue
Block a user