Even more RAM reduction

This commit is contained in:
CinderSocket
2026-03-25 01:59:59 -07:00
parent 6ebb29f66d
commit 2dc6779a55
15 changed files with 205 additions and 56 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
#define TAG "APDU_Runner"
// Max length of firmware upgrade: 731 bytes
#define SEADER_APDU_MAX_LEN 732
#define SEADER_APDU_MAX_LEN 732
#define SEADER_APDU_RUNNER_HEX_LOG_MAX_BYTES 32U
void seader_apdu_runner_cleanup(Seader* seader, SeaderWorkerEvent event) {
+3 -3
View File
@@ -1,7 +1,7 @@
#include "seader_i.h"
#include "ccid_logic.h"
#define TAG "SeaderCCID"
#define TAG "SeaderCCID"
#define SEADER_CCID_HEX_LOG_MAX_BYTES 32U
const uint8_t SAM_ATR[] =
{0x3b, 0x95, 0x96, 0x80, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0x47, 0x72, 0x61, 0x63, 0x65, 0x13};
@@ -44,8 +44,8 @@ static void seader_ccid_log_hex(const char* prefix, const uint8_t* data, size_t
return;
}
const size_t display_len = len > SEADER_CCID_HEX_LOG_MAX_BYTES ? SEADER_CCID_HEX_LOG_MAX_BYTES :
len;
const size_t display_len =
len > SEADER_CCID_HEX_LOG_MAX_BYTES ? SEADER_CCID_HEX_LOG_MAX_BYTES : len;
char hex[(SEADER_CCID_HEX_LOG_MAX_BYTES * 2U) + 1U];
for(size_t i = 0; i < display_len; i++) {
+1 -1
View File
@@ -247,7 +247,7 @@ static void plugin_hf_iso14443a_transmit(
return;
}
BitBuffer* tx_buffer = bit_buffer_alloc(len + 1);
BitBuffer* tx_buffer = bit_buffer_alloc(len + 1U);
BitBuffer* rx_buffer = bit_buffer_alloc(HF_PLUGIN_POLLER_MAX_BUFFER_SIZE);
if(!tx_buffer || !rx_buffer) {
FURI_LOG_E(TAG, "Failed to allocate 14A buffers");
+1 -1
View File
@@ -12,7 +12,7 @@
#include "t_1_logic.h"
/* Keep the host harness aligned with the production UART scratchpad size. */
#define SEADER_UART_RX_BUF_SIZE (300)
#define SEADER_UART_RX_BUF_SIZE (272)
#define FURI_LOG_W(tag, fmt, ...) ((void)0)
#define furi_check(expr) \
do { \
+17 -3
View File
@@ -355,8 +355,14 @@ PicopassError seader_worker_fake_epurse_update(BitBuffer* tx_buffer, BitBuffer*
void seader_virtual_picopass_state_machine(Seader* seader, uint8_t* buffer, size_t len) {
BitBuffer* tx_buffer = bit_buffer_alloc(len);
bit_buffer_append_bytes(tx_buffer, buffer, len);
BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE);
if(!tx_buffer || !rx_buffer) {
FURI_LOG_E(TAG, "Failed to allocate virtual Picopass buffers");
if(tx_buffer) bit_buffer_free(tx_buffer);
if(rx_buffer) bit_buffer_free(rx_buffer);
return;
}
bit_buffer_append_bytes(tx_buffer, buffer, len);
uint8_t config[PICOPASS_BLOCK_LEN] = {0x12, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0xff, 0x3c};
uint8_t sr_aia[PICOPASS_BLOCK_LEN] = {0xFF, 0xff, 0xff, 0xff, 0xFF, 0xFf, 0xff, 0xFF};
@@ -1208,9 +1214,18 @@ void seader_iso15693_transmit(
BitBuffer* tx_buffer = bit_buffer_alloc(len);
BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE);
PicopassError error = PicopassErrorNone;
if(!tx_buffer || !rx_buffer) {
FURI_LOG_E(TAG, "Failed to allocate Picopass tx/rx buffers");
if(tx_buffer) bit_buffer_free(tx_buffer);
if(rx_buffer) bit_buffer_free(rx_buffer);
if(seader_worker) {
seader_worker->stage = SeaderPollerEventTypeFail;
}
return;
}
do {
bit_buffer_append_bytes(tx_buffer, buffer, len);
@@ -1238,7 +1253,6 @@ void seader_iso15693_transmit(
bit_buffer_get_size_bytes(rx_buffer));
} while(false);
bit_buffer_free(tx_buffer);
bit_buffer_free(rx_buffer);
}
+42 -1
View File
@@ -4,6 +4,46 @@
#define TAG "SeaderCredentialInfoScene"
static void seader_scene_credential_info_alloc_strings(Seader* seader) {
furi_check(seader);
if(!seader->temp_string1) {
seader->temp_string1 = furi_string_alloc();
furi_check(seader->temp_string1);
}
if(!seader->temp_string2) {
seader->temp_string2 = furi_string_alloc();
furi_check(seader->temp_string2);
}
if(!seader->temp_string3) {
seader->temp_string3 = furi_string_alloc();
furi_check(seader->temp_string3);
}
if(!seader->temp_string4) {
seader->temp_string4 = furi_string_alloc();
furi_check(seader->temp_string4);
}
}
static void seader_scene_credential_info_free_strings(Seader* seader) {
furi_check(seader);
if(seader->temp_string1) {
furi_string_free(seader->temp_string1);
seader->temp_string1 = NULL;
}
if(seader->temp_string2) {
furi_string_free(seader->temp_string2);
seader->temp_string2 = NULL;
}
if(seader->temp_string3) {
furi_string_free(seader->temp_string3);
seader->temp_string3 = NULL;
}
if(seader->temp_string4) {
furi_string_free(seader->temp_string4);
seader->temp_string4 = NULL;
}
}
static bool seader_credential_is_picopass_sio_context(const SeaderCredential* credential) {
return credential && (credential->type == SeaderCredentialTypePicopass ||
(credential->has_pacs_media_type &&
@@ -26,7 +66,7 @@ void seader_scene_credential_info_on_enter(void* context) {
seader_wiegand_plugin_acquire(seader);
Widget* widget = seader->widget;
// Use reusable strings instead of allocating new ones
seader_scene_credential_info_alloc_strings(seader);
FuriString* type_str = seader->temp_string1;
FuriString* bitlength_str = seader->temp_string2;
FuriString* credential_str = seader->temp_string3;
@@ -119,5 +159,6 @@ void seader_scene_credential_info_on_exit(void* context) {
// Clear views
widget_reset(seader->widget);
seader_scene_credential_info_free_strings(seader);
seader_wiegand_plugin_release(seader);
}
+21
View File
@@ -1,11 +1,24 @@
#include "../seader_i.h"
#include <dolphin/dolphin.h>
static void seader_scene_formats_alloc_strings(Seader* seader) {
furi_check(seader);
if(!seader->text_box_store) {
seader->text_box_store = furi_string_alloc();
furi_check(seader->text_box_store);
}
if(!seader->temp_string1) {
seader->temp_string1 = furi_string_alloc();
furi_check(seader->temp_string1);
}
}
void seader_scene_formats_on_enter(void* context) {
Seader* seader = context;
PluginWiegand* plugin = seader_wiegand_plugin_acquire(seader) ? seader->plugin_wiegand : NULL;
SeaderCredential* credential = seader->credential;
seader_scene_formats_alloc_strings(seader);
FuriString* str = seader->text_box_store;
furi_string_reset(str);
@@ -51,5 +64,13 @@ void seader_scene_formats_on_exit(void* context) {
// Clear views
text_box_reset(seader->text_box);
if(seader->text_box_store) {
furi_string_free(seader->text_box_store);
seader->text_box_store = NULL;
}
if(seader->temp_string1) {
furi_string_free(seader->temp_string1);
seader->temp_string1 = NULL;
}
seader_wiegand_plugin_release(seader);
}
+42 -1
View File
@@ -4,6 +4,46 @@
#define TAG "SeaderSceneReadCardSuccess"
static void seader_scene_read_card_success_alloc_strings(Seader* seader) {
furi_check(seader);
if(!seader->temp_string1) {
seader->temp_string1 = furi_string_alloc();
furi_check(seader->temp_string1);
}
if(!seader->temp_string2) {
seader->temp_string2 = furi_string_alloc();
furi_check(seader->temp_string2);
}
if(!seader->temp_string3) {
seader->temp_string3 = furi_string_alloc();
furi_check(seader->temp_string3);
}
if(!seader->temp_string4) {
seader->temp_string4 = furi_string_alloc();
furi_check(seader->temp_string4);
}
}
static void seader_scene_read_card_success_free_strings(Seader* seader) {
furi_check(seader);
if(seader->temp_string1) {
furi_string_free(seader->temp_string1);
seader->temp_string1 = NULL;
}
if(seader->temp_string2) {
furi_string_free(seader->temp_string2);
seader->temp_string2 = NULL;
}
if(seader->temp_string3) {
furi_string_free(seader->temp_string3);
seader->temp_string3 = NULL;
}
if(seader->temp_string4) {
furi_string_free(seader->temp_string4);
seader->temp_string4 = NULL;
}
}
static bool seader_credential_is_picopass_sio_context(const SeaderCredential* credential) {
return credential && (credential->type == SeaderCredentialTypePicopass ||
(credential->has_pacs_media_type &&
@@ -28,7 +68,7 @@ void seader_scene_read_card_success_on_enter(void* context) {
PluginWiegand* plugin = seader_wiegand_plugin_acquire(seader) ? seader->plugin_wiegand : NULL;
Widget* widget = seader->widget;
// Use reusable strings instead of allocating new ones
seader_scene_read_card_success_alloc_strings(seader);
FuriString* type_str = seader->temp_string1;
FuriString* bitlength_str = seader->temp_string2;
FuriString* credential_str = seader->temp_string3;
@@ -166,5 +206,6 @@ void seader_scene_read_card_success_on_exit(void* context) {
// Clear view
widget_reset(seader->widget);
seader_scene_read_card_success_free_strings(seader);
seader_wiegand_plugin_release(seader);
}
+34 -1
View File
@@ -3,6 +3,38 @@
#define TAG "SeaderSamInfoScene"
static void seader_scene_sam_info_alloc_strings(Seader* seader) {
furi_check(seader);
if(!seader->temp_string1) {
seader->temp_string1 = furi_string_alloc();
furi_check(seader->temp_string1);
}
if(!seader->temp_string2) {
seader->temp_string2 = furi_string_alloc();
furi_check(seader->temp_string2);
}
if(!seader->temp_string3) {
seader->temp_string3 = furi_string_alloc();
furi_check(seader->temp_string3);
}
}
static void seader_scene_sam_info_free_strings(Seader* seader) {
furi_check(seader);
if(seader->temp_string1) {
furi_string_free(seader->temp_string1);
seader->temp_string1 = NULL;
}
if(seader->temp_string2) {
furi_string_free(seader->temp_string2);
seader->temp_string2 = NULL;
}
if(seader->temp_string3) {
furi_string_free(seader->temp_string3);
seader->temp_string3 = NULL;
}
}
void seader_scene_sam_info_widget_callback(GuiButtonType result, InputType type, void* context) {
Seader* seader = context;
if(type == InputTypeShort) {
@@ -14,7 +46,7 @@ void seader_scene_sam_info_on_enter(void* context) {
Seader* seader = context;
Widget* widget = seader->widget;
// Use reusable string instead of allocating new one
seader_scene_sam_info_alloc_strings(seader);
FuriString* fw_str = seader->temp_string1;
FuriString* info_str = seader->temp_string2;
FuriString* uhf_str = seader->temp_string3;
@@ -66,4 +98,5 @@ void seader_scene_sam_info_on_exit(void* context) {
// Clear views
widget_reset(seader->widget);
seader_scene_sam_info_free_strings(seader);
}
+5 -11
View File
@@ -21,10 +21,7 @@ void seader_scene_save_name_on_enter(void* context) {
name_generator_make_random(seader->save_name_buf, sizeof(seader->save_name_buf));
cred_name_empty = true;
} else {
strlcpy(
seader->save_name_buf,
seader->credential->name,
sizeof(seader->save_name_buf));
strlcpy(seader->save_name_buf, seader->credential->name, sizeof(seader->save_name_buf));
}
text_input_set_header_text(text_input, "Name the credential");
text_input_set_result_callback(
@@ -35,8 +32,8 @@ void seader_scene_save_name_on_enter(void* context) {
SEADER_CRED_NAME_MAX_LEN,
cred_name_empty);
// Use reusable string instead of allocating new one
FuriString* folder_path = seader->temp_string1;
FuriString* folder_path = furi_string_alloc();
furi_check(folder_path);
if(furi_string_end_with(seader->credential->load_path, SEADER_APP_EXTENSION)) {
path_extract_dirname(furi_string_get_cstr(seader->credential->load_path), folder_path);
} else {
@@ -48,8 +45,7 @@ void seader_scene_save_name_on_enter(void* context) {
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewTextInput);
// No need to free folder_path as it's reused from seader struct
furi_string_free(folder_path);
}
bool seader_scene_save_name_on_event(void* context, SceneManagerEvent event) {
@@ -64,9 +60,7 @@ bool seader_scene_save_name_on_event(void* context, SceneManagerEvent event) {
seader_credential_delete(seader->credential, true);
}
strlcpy(
seader->credential->name,
seader->save_name_buf,
sizeof(seader->credential->name));
seader->credential->name, seader->save_name_buf, sizeof(seader->credential->name));
if(seader_credential_save(seader->credential, seader->save_name_buf)) {
scene_manager_next_scene(seader->scene_manager, SeaderSceneSaveSuccess);
consumed = true;
+13 -11
View File
@@ -533,18 +533,18 @@ Seader* seader_alloc() {
seader->text_box = text_box_alloc();
view_dispatcher_add_view(
seader->view_dispatcher, SeaderViewTextBox, text_box_get_view(seader->text_box));
seader->text_box_store = furi_string_alloc();
seader->text_box_store = NULL;
// Custom Widget
seader->widget = widget_alloc();
view_dispatcher_add_view(
seader->view_dispatcher, SeaderViewWidget, widget_get_view(seader->widget));
// Allocate reusable strings for scene optimization
seader->temp_string1 = furi_string_alloc();
seader->temp_string2 = furi_string_alloc();
seader->temp_string3 = furi_string_alloc();
seader->temp_string4 = furi_string_alloc();
// Scene strings are allocated lazily by the scenes that need them.
seader->temp_string1 = NULL;
seader->temp_string2 = NULL;
seader->temp_string3 = NULL;
seader->temp_string4 = NULL;
seader->plugin_manager = NULL;
seader->plugin_wiegand = NULL;
@@ -618,17 +618,19 @@ void seader_free(Seader* seader) {
// TextBox
view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewTextBox);
text_box_free(seader->text_box);
furi_string_free(seader->text_box_store);
if(seader->text_box_store) {
furi_string_free(seader->text_box_store);
}
// Custom Widget
view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewWidget);
widget_free(seader->widget);
// Free reusable strings
furi_string_free(seader->temp_string1);
furi_string_free(seader->temp_string2);
furi_string_free(seader->temp_string3);
furi_string_free(seader->temp_string4);
if(seader->temp_string1) furi_string_free(seader->temp_string1);
if(seader->temp_string2) furi_string_free(seader->temp_string2);
if(seader->temp_string3) furi_string_free(seader->temp_string3);
if(seader->temp_string4) furi_string_free(seader->temp_string4);
// View Dispatcher
view_dispatcher_free(seader->view_dispatcher);
+1 -1
View File
@@ -12,7 +12,7 @@
#include "t_1_logic.h"
// https://ww1.microchip.com/downloads/en/DeviceDoc/00001561C.pdf
#define SEADER_UART_RX_BUF_SIZE (300)
#define SEADER_UART_RX_BUF_SIZE (272)
#define SEADER_CCID_SLOT_COUNT (2U)
typedef struct BitBuffer BitBuffer;
+1 -3
View File
@@ -2,9 +2,7 @@
#define SEADER_HF_READ_PLAN_MAX_TYPES 3U
static void seader_hf_read_plan_add_type(
SeaderHfReadPlan* plan,
SeaderCredentialType type) {
static void seader_hf_read_plan_add_type(SeaderHfReadPlan* plan, SeaderCredentialType type) {
if(type == SeaderCredentialTypeNone) {
return;
}
+22 -17
View File
@@ -7,8 +7,8 @@
#define TAG "SeaderWorker"
#define APDU_HEADER_LEN 5
#define ASN1_PREFIX 6
#define APDU_HEADER_LEN 5
#define ASN1_PREFIX 6
#define SEADER_HEX_LOG_MAX_BYTES 32U
// #define ASN1_DEBUG true
@@ -69,10 +69,8 @@ static void seader_worker_release_apdu_slot(SeaderWorker* seader_worker, uint8_t
}
}
static bool seader_worker_dequeue_apdu(
SeaderWorker* seader_worker,
uint8_t* slot_index,
FuriWait timeout) {
static bool
seader_worker_dequeue_apdu(SeaderWorker* seader_worker, uint8_t* slot_index, FuriWait timeout) {
furi_assert(seader_worker);
furi_assert(slot_index);
return furi_message_queue_get(seader_worker->messages, slot_index, timeout) == FuriStatusOk;
@@ -250,10 +248,22 @@ SeaderWorker* seader_worker_alloc() {
// Worker thread attributes
seader_worker->thread =
furi_thread_alloc_ex("SeaderWorker", 6144, seader_worker_task, seader_worker);
furi_thread_alloc_ex("SeaderWorker", 5120, seader_worker_task, seader_worker);
seader_worker->messages = furi_message_queue_alloc(2, sizeof(uint8_t));
seader_worker->apdu_slots = calloc(SEADER_WORKER_APDU_SLOT_COUNT, sizeof(SeaderAPDU));
if(!seader_worker->thread || !seader_worker->messages || !seader_worker->apdu_slots) {
if(seader_worker->thread) {
furi_thread_free(seader_worker->thread);
}
if(seader_worker->messages) {
furi_message_queue_free(seader_worker->messages);
}
free(seader_worker->apdu_slots);
free(seader_worker);
return NULL;
}
seader_worker->callback = NULL;
seader_worker->context = NULL;
seader_worker->storage = furi_record_open(RECORD_STORAGE);
@@ -559,14 +569,9 @@ void seader_worker_reading(Seader* seader) {
SeaderWorker* seader_worker = seader->worker;
FURI_LOG_I(TAG, "Reading loop started");
if(!seader_hf_plugin_acquire(seader) || !seader->plugin_hf || !seader->hf_plugin_ctx) {
FURI_LOG_E(TAG, "HF plugin unavailable");
strlcpy(seader->read_error, "HF plugin unavailable", sizeof(seader->read_error));
if(seader_worker->callback) {
seader_worker->callback(SeaderWorkerEventFail, seader_worker->context);
}
return;
}
furi_check(seader_hf_plugin_acquire(seader));
furi_check(seader->plugin_hf);
furi_check(seader->hf_plugin_ctx);
while(seader_worker->state == SeaderWorkerStateReading) {
bool detected = false;
@@ -595,8 +600,8 @@ void seader_worker_reading(Seader* seader) {
break;
} else if(read_plan.decision == SeaderHfReadDecisionStartRead) {
FURI_LOG_I(TAG, "HF start read for type=%d", read_plan.type_to_read);
detected =
seader->plugin_hf->start_read_for_type(seader->hf_plugin_ctx, read_plan.type_to_read);
detected = seader->plugin_hf->start_read_for_type(
seader->hf_plugin_ctx, read_plan.type_to_read);
if(detected) {
seader->hf_session_state = SeaderHfSessionStateActive;
}
+1 -1
View File
@@ -6,7 +6,7 @@
#include "t_1_logic.h"
#define TAG "Seader:T=1"
#define TAG "Seader:T=1"
#define SEADER_T1_MAX_FRAME_LEN (3U + SEADER_T1_IFS_MAX + 1U)
static SeaderT1State* seader_t1_state(SeaderUartBridge* seader_uart) {