mirror of
https://protopirate.net/ProtoPirate/ProtoPirate.git
synced 2026-10-22 20:11:18 +00:00
* Removed dependencies on App Struct in Plugin Module * Cleaned up headers * Only check navigation events if plugin doesnt handle the event
259 lines
9.7 KiB
C
259 lines
9.7 KiB
C
#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;
|
|
}
|