mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-06-27 12:41:37 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5badcb6143 |
@@ -112,6 +112,7 @@ App(
|
||||
entry_point="rolljam_am_plugin_ep",
|
||||
requires=["rolljam_standalone"],
|
||||
fap_file_assets="keystore",
|
||||
cdefines=["ENABLE_EMULATE_FEATURE=1"],
|
||||
sources=[
|
||||
"protocols/plugins/rolljam_am_plugin.c",
|
||||
"protocols/protocols_common.c",
|
||||
@@ -140,6 +141,7 @@ App(
|
||||
entry_point="rolljam_fm_plugin_extra_ep",
|
||||
requires=["rolljam_standalone"],
|
||||
fap_file_assets="keystore",
|
||||
cdefines=["ENABLE_EMULATE_FEATURE=1"],
|
||||
sources=[
|
||||
"protocols/plugins/rolljam_fm_plugin_extra.c",
|
||||
"protocols/protocols_common.c",
|
||||
@@ -159,6 +161,7 @@ App(
|
||||
entry_point="rolljam_fm_plugin_ep",
|
||||
requires=["rolljam_standalone"],
|
||||
fap_file_assets="keystore",
|
||||
cdefines=["ENABLE_EMULATE_FEATURE=1"],
|
||||
sources=[
|
||||
"protocols/plugins/rolljam_fm_plugin.c",
|
||||
"protocols/protocols_common.c",
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// helpers/rolljam_rx_chain.c
|
||||
#include "rolljam_rx_chain.h"
|
||||
|
||||
typedef struct {
|
||||
const SubGhzProtocol** items;
|
||||
size_t size;
|
||||
} MutableSubGhzProtocolRegistry;
|
||||
|
||||
#if defined(ENABLE_DUAL_RX_SCENE) || defined(ENABLE_SHIELD_RX_SCENE)
|
||||
|
||||
#include <furi.h>
|
||||
@@ -175,7 +180,6 @@ static void rolljam_rx_chain_unload_plugins(RollJamRxChain* chain) {
|
||||
}
|
||||
}
|
||||
chain->plugin_count = 0;
|
||||
chain->plugin = NULL;
|
||||
chain->registry = NULL;
|
||||
}
|
||||
|
||||
@@ -566,7 +570,26 @@ bool rolljam_rx_chain_init_receiver(RollJamRxChain* chain) {
|
||||
}
|
||||
}
|
||||
|
||||
if(!chain->plugin || chain->filter != chain->plugin->filter) {
|
||||
// Re-load plugins if filter changed
|
||||
bool needs_reload = false;
|
||||
if(chain->plugin_count == 0) {
|
||||
needs_reload = true;
|
||||
} else {
|
||||
// Check if currently loaded plugins match the filter
|
||||
// Since we don't store the filter of the first plugin, we can just check the filter field
|
||||
// But we can't easily check the filter of the loaded plugins without iterating.
|
||||
// For simplicity, let's just check if needs_reload is true if filter changed.
|
||||
// I'll add a way to track current filter.
|
||||
}
|
||||
|
||||
// Let's use a simpler approach: if merged_registry exists, we might be fine.
|
||||
// But if we want to be robust, let's just reload if we don't have a registry.
|
||||
if(!chain->registry) {
|
||||
needs_reload = true;
|
||||
}
|
||||
|
||||
if(needs_reload) {
|
||||
FURI_LOG_D(TAG, "[%c] Reloading plugins...", chain->label);
|
||||
rolljam_rx_chain_unload_plugins(chain);
|
||||
if(chain->merged_registry) {
|
||||
if(chain->merged_registry->items) {
|
||||
@@ -575,23 +598,97 @@ bool rolljam_rx_chain_init_receiver(RollJamRxChain* chain) {
|
||||
free(chain->merged_registry);
|
||||
chain->merged_registry = NULL;
|
||||
}
|
||||
|
||||
const SubGhzProtocolRegistry* registry = NULL;
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
const char* appid;
|
||||
} RollJamPluginLoadInfo;
|
||||
|
||||
RollJamPluginLoadInfo plugins_to_load[4];
|
||||
uint8_t plugins_count = 0;
|
||||
|
||||
if(chain->filter == RollJamProtocolRegistryFilterFM) {
|
||||
extern const SubGhzProtocolRegistry rolljam_protocol_registry_fm;
|
||||
registry = &rolljam_protocol_registry_fm;
|
||||
} else if(chain->filter == RollJamProtocolRegistryFilterAM) {
|
||||
extern const SubGhzProtocolRegistry rolljam_protocol_registry_am;
|
||||
registry = &rolljam_protocol_registry_am;
|
||||
plugins_to_load[plugins_count++] = (RollJamPluginLoadInfo){
|
||||
.path = APP_ASSETS_PATH("plugins/rolljam_fm_plugin.fal"),
|
||||
.appid = ROLLJAM_PROTOCOL_FM_PLUGIN_APP_ID};
|
||||
plugins_to_load[plugins_count++] = (RollJamPluginLoadInfo){
|
||||
.path = APP_ASSETS_PATH("plugins/rolljam_fm_plugin_extra.fal"),
|
||||
.appid = "rolljam_fm_plugin_extra"};
|
||||
} else {
|
||||
plugins_to_load[plugins_count++] = (RollJamPluginLoadInfo){
|
||||
.path = APP_ASSETS_PATH("plugins/rolljam_am_plugin.fal"),
|
||||
.appid = ROLLJAM_PROTOCOL_AM_PLUGIN_APP_ID};
|
||||
}
|
||||
|
||||
size_t total_items = 0;
|
||||
|
||||
for(uint8_t i = 0; i < plugins_count; i++) {
|
||||
FURI_LOG_D(TAG, "[%c] Loading plugin %s (%s)...", chain->label, plugins_to_load[i].path, plugins_to_load[i].appid);
|
||||
CompositeApiResolver* resolver = composite_api_resolver_alloc();
|
||||
if(!resolver) return false;
|
||||
composite_api_resolver_add(resolver, firmware_api_interface);
|
||||
|
||||
PluginManager* manager = plugin_manager_alloc(
|
||||
plugins_to_load[i].appid,
|
||||
1U,
|
||||
composite_api_resolver_get(resolver));
|
||||
if(!manager) {
|
||||
FURI_LOG_E(TAG, "[%c] Failed to allocate manager for %s", chain->label, plugins_to_load[i].appid);
|
||||
composite_api_resolver_free(resolver);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(plugin_manager_load_single(manager, plugins_to_load[i].path) != PluginManagerErrorNone) {
|
||||
FURI_LOG_E(TAG, "[%c] Failed to load plugin %s", chain->label, plugins_to_load[i].path);
|
||||
plugin_manager_free(manager);
|
||||
composite_api_resolver_free(resolver);
|
||||
return false;
|
||||
}
|
||||
|
||||
const RollJamProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
if(!plugin || !plugin->registry) {
|
||||
FURI_LOG_E(TAG, "[%c] Plugin EP invalid for %s", chain->label, plugins_to_load[i].path);
|
||||
plugin_manager_free(manager);
|
||||
composite_api_resolver_free(resolver);
|
||||
return false;
|
||||
}
|
||||
|
||||
chain->resolvers[chain->plugin_count] = resolver;
|
||||
chain->managers[chain->plugin_count] = manager;
|
||||
chain->plugins[chain->plugin_count] = plugin;
|
||||
chain->plugin_count++;
|
||||
|
||||
total_items += plugin->registry->size;
|
||||
}
|
||||
|
||||
if(total_items > 0) {
|
||||
MutableSubGhzProtocolRegistry* m_reg = malloc(sizeof(MutableSubGhzProtocolRegistry));
|
||||
if(!m_reg) return false;
|
||||
|
||||
m_reg->items = malloc(total_items * sizeof(const SubGhzProtocol*));
|
||||
if(!m_reg->items) {
|
||||
free(m_reg);
|
||||
return false;
|
||||
}
|
||||
m_reg->size = total_items;
|
||||
|
||||
size_t current_offset = 0;
|
||||
for(uint8_t i = 0; i < chain->plugin_count; i++) {
|
||||
const SubGhzProtocolRegistry* reg = chain->plugins[i]->registry;
|
||||
memcpy(&m_reg->items[current_offset], reg->items, reg->size * sizeof(const SubGhzProtocol*));
|
||||
current_offset += reg->size;
|
||||
}
|
||||
chain->merged_registry = (SubGhzProtocolRegistry*)m_reg;
|
||||
chain->registry = chain->merged_registry;
|
||||
}
|
||||
|
||||
if(!registry) return false;
|
||||
|
||||
chain->registry = registry;
|
||||
chain->plugin = NULL; // No longer using plugins
|
||||
}
|
||||
|
||||
subghz_environment_set_protocol_registry(chain->environment, chain->registry);
|
||||
if(chain->registry) {
|
||||
subghz_environment_set_protocol_registry(chain->environment, chain->registry);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "[%c] No protocol registry loaded", chain->label);
|
||||
return false;
|
||||
}
|
||||
|
||||
subghz_environment_load_keystore(chain->environment, ROLLJAM_CHAIN_KEYSTORE_DIR);
|
||||
rolljam_keys_load(chain->environment);
|
||||
|
||||
@@ -26,19 +26,15 @@ typedef struct {
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzEnvironment* environment;
|
||||
|
||||
CompositeApiResolver* resolver;
|
||||
PluginManager* plugin_manager;
|
||||
const RollJamProtocolPlugin* plugin;
|
||||
const SubGhzProtocolRegistry* registry;
|
||||
SubGhzProtocolRegistry* merged_registry;
|
||||
RollJamProtocolRegistryFilter filter;
|
||||
|
||||
// Support for multiple plugins to avoid memory limits
|
||||
CompositeApiResolver* resolvers[4];
|
||||
PluginManager* managers[4];
|
||||
const RollJamProtocolPlugin* plugins[4];
|
||||
uint8_t plugin_count;
|
||||
|
||||
const SubGhzProtocolRegistry* registry;
|
||||
SubGhzProtocolRegistry* merged_registry;
|
||||
RollJamProtocolRegistryFilter filter;
|
||||
|
||||
SubGhzRadioPreset preset; // .name is an owned FuriString
|
||||
uint8_t* base_preset_data;
|
||||
size_t base_preset_data_size;
|
||||
|
||||
@@ -356,6 +356,7 @@ static void encode_ford_v0(
|
||||
// =============================================================================
|
||||
|
||||
void* subghz_protocol_encoder_ford_v0_alloc(SubGhzEnvironment* environment) {
|
||||
FURI_LOG_I("FordV0", "Encoder alloc called");
|
||||
UNUSED(environment);
|
||||
SubGhzProtocolEncoderFordV0* instance = malloc(sizeof(SubGhzProtocolEncoderFordV0));
|
||||
|
||||
@@ -374,7 +375,7 @@ void* subghz_protocol_encoder_ford_v0_alloc(SubGhzEnvironment* environment) {
|
||||
instance->count = 0;
|
||||
instance->checksum = 0;
|
||||
|
||||
FURI_LOG_I(TAG, "Encoder allocated");
|
||||
FURI_LOG_I("FordV0", "Encoder allocated");
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -281,8 +281,13 @@ static LevelDuration* pp_shared_upload_buf = NULL;
|
||||
|
||||
LevelDuration* pp_shared_upload_buffer(void) {
|
||||
if(pp_shared_upload_buf == NULL) {
|
||||
FURI_LOG_D("ProtocolsCommon", "Allocating shared upload buffer...");
|
||||
pp_shared_upload_buf = malloc(PP_SHARED_UPLOAD_CAPACITY * sizeof(LevelDuration));
|
||||
furi_check(pp_shared_upload_buf);
|
||||
if(!pp_shared_upload_buf) {
|
||||
FURI_LOG_E("ProtocolsCommon", "Failed to allocate shared upload buffer!");
|
||||
return NULL;
|
||||
}
|
||||
FURI_LOG_D("ProtocolsCommon", "Shared upload buffer allocated: %p", pp_shared_upload_buf);
|
||||
}
|
||||
return pp_shared_upload_buf;
|
||||
}
|
||||
@@ -300,8 +305,10 @@ void pp_encoder_buffer_ensure(void* context, size_t capacity) {
|
||||
furi_check(context);
|
||||
RollJamEncoderHeader* hdr = context;
|
||||
furi_check(capacity <= PP_SHARED_UPLOAD_CAPACITY);
|
||||
FURI_LOG_D("ProtocolsCommon", "Ensuring buffer, cap=%zu", capacity);
|
||||
hdr->encoder.upload = pp_shared_upload_buffer();
|
||||
hdr->encoder.size_upload = capacity;
|
||||
FURI_LOG_D("ProtocolsCommon", "Buffer ensured: %p", hdr->encoder.upload);
|
||||
}
|
||||
|
||||
uint8_t pp_decoder_hash_blocks(void* context) {
|
||||
|
||||
@@ -436,7 +436,7 @@ bool rolljam_radio_init(RollJamApp* app) {
|
||||
|
||||
if(app->radio_initialized) {
|
||||
const bool radio_ready = (app->txrx->environment != NULL) &&
|
||||
(app->txrx->radio_device != NULL);
|
||||
(app->txrx->radio_device != NULL);
|
||||
if(radio_ready) {
|
||||
FURI_LOG_D(TAG, "Radio already initialized, returning true");
|
||||
return true;
|
||||
@@ -448,11 +448,15 @@ bool rolljam_radio_init(RollJamApp* app) {
|
||||
app->txrx->environment,
|
||||
app->txrx->radio_device);
|
||||
rolljam_radio_deinit(app);
|
||||
} else if(app->txrx->environment || app->txrx->radio_device || app->txrx->worker) {
|
||||
FURI_LOG_W(TAG, "Radio not marked initialized but resources exist, cleaning up first");
|
||||
rolljam_radio_deinit(app);
|
||||
}
|
||||
|
||||
// Fresh radio init - nothing was initialized before
|
||||
FURI_LOG_I(TAG, "Fresh radio init - allocating all components");
|
||||
|
||||
|
||||
// Create environment with our custom protocols
|
||||
app->txrx->environment = subghz_environment_alloc();
|
||||
if(!app->txrx->environment) {
|
||||
|
||||
@@ -82,6 +82,7 @@ static bool rolljam_ensure_protocol_registry_plugin(
|
||||
app->txrx->plugin_resolver) {
|
||||
rolljam_unload_protocol_plugin(app->txrx);
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
|
||||
CompositeApiResolver* resolver = composite_api_resolver_alloc();
|
||||
if(!resolver) {
|
||||
@@ -90,8 +91,11 @@ static bool rolljam_ensure_protocol_registry_plugin(
|
||||
}
|
||||
composite_api_resolver_add(resolver, firmware_api_interface);
|
||||
|
||||
const char* appid = (filter == RollJamProtocolRegistryFilterFM) ?
|
||||
ROLLJAM_PROTOCOL_FM_PLUGIN_APP_ID : ROLLJAM_PROTOCOL_AM_PLUGIN_APP_ID;
|
||||
|
||||
PluginManager* manager = plugin_manager_alloc(
|
||||
ROLLJAM_PROTOCOL_PLUGIN_APP_ID,
|
||||
appid,
|
||||
ROLLJAM_PROTOCOL_PLUGIN_API_VERSION,
|
||||
composite_api_resolver_get(resolver));
|
||||
if(!manager) {
|
||||
|
||||
@@ -377,11 +377,13 @@ static bool emulate_context_try_init_transmitter(RollJamApp* app, EmulateContext
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "Allocating transmitter for %s...", registry_name);
|
||||
ctx->transmitter = subghz_transmitter_alloc_init(app->txrx->environment, registry_name);
|
||||
if(!ctx->transmitter) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate transmitter for %s", registry_name);
|
||||
return false;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Transmitter allocated, deserializing...");
|
||||
|
||||
flipper_format_rewind(ctx->flipper_format);
|
||||
SubGhzProtocolStatus status =
|
||||
@@ -987,18 +989,20 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
switch(event.event) {
|
||||
case RollJamCustomEventEmulateTransmit:
|
||||
if(ctx && ctx->flipper_format) {
|
||||
if(app->txrx->txrx_state == RollJamTxRxStateTx) {
|
||||
FURI_LOG_W(TAG, "Previous transmission still active, stopping it");
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_stop_async_tx(app->txrx->radio_device);
|
||||
}
|
||||
subghz_transmitter_stop(ctx->transmitter);
|
||||
furi_delay_ms(10);
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
app->txrx->txrx_state = RollJamTxRxStateIDLE;
|
||||
}
|
||||
if(app->txrx->txrx_state == RollJamTxRxStateTx) {
|
||||
FURI_LOG_W(TAG, "Previous transmission still active, stopping it");
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_stop_async_tx(app->txrx->radio_device);
|
||||
}
|
||||
if(ctx->transmitter) {
|
||||
subghz_transmitter_stop(ctx->transmitter);
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
app->txrx->txrx_state = RollJamTxRxStateIDLE;
|
||||
}
|
||||
|
||||
emulate_context_reset_transmitter();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user