Compare commits

...

1 Commits

8 changed files with 155 additions and 39 deletions
@@ -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) {
+5 -1
View File
@@ -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) {
+5 -1
View File
@@ -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();