From 816830ebb9f0e3cdd60816a11d7e3e12e34f5a88 Mon Sep 17 00:00:00 2001 From: jay candel Date: Sun, 3 Nov 2024 01:17:12 +0800 Subject: [PATCH 1/5] Add files via upload --- changelog.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..3b39aea --- /dev/null +++ b/changelog.md @@ -0,0 +1,82 @@ +# Changelog + +## v1.0.1 +- Revamped menu structure with logical grouping (scanning, beacon spam, attacks, etc.) +- Simplified command addition and cleaned up documentation in `menu.c` +- Centralized and enum-based settings metadata for improved validation and extensibility +- Enhanced settings with Stop-on-Back feature and ESP reboot command +- Added ESP connection verification and clearer error messaging +- Enabled automatic connectivity check and error recovery for ESP issues +- Unified UI with metadata-driven consistency and better type safety +- Simplified UI view switching and improved error display +- Refined code organization, separating concerns, removing redundancy, and standardizing error handling + +## v1.0.2 +- Added confirmation dialogs for WebUI-dependent features in the UI +- Improved settings menu with actions submenu, NVS clearing, and log clearing +- Enhanced memory management and improved settings storage/loading robustness +- Added contextual help for WebUI configuration and confirmation dialogs for command safety +- Improved view navigation, state management, and memory cleanup processes +- Added safeguards against `furi_check` failures with NULL checks and memory initialization + +## v1.0.3 +- Enhanced confirmation view structure and readability with better text alignment +- Added confirmation for "Clear Log Files" with a permanent action warning +- Enabled back press exit on confirmation views with callback context handling +- Improved memory management with context cleanup, view state tracking, and transition fixes +- Added NULL checks, fixed memory leaks, and added state tracking for dialogs + +## v1.0.4 +- Refined confirmation view line breaks for readability +- Improved ESP Connectity check to decrease false negatives +- Added optional filtering to UART output to improve readability (BETA) +- Added 'App Info' Button in Settings +- Misc Changes (mostly to UI) + +## v1.0.5 +- Commands will silently fail if UART isn't working rather than crashing +- Fixed double-free memory issue by removing stream buffer cleanup from the worker thread +- Reorganized initialization order +- UART initialization happens in background +- Serial operations don't block app startup +- Optimized storage initialization by deferring file operations until needed +- Improved directory creation efficiency in storage handling + +## v1.0.6 +- Replaced 'Info' command in ESP Check with 'Stop' +- Slightly improved optional UART filtering +- Memory safety improvements. +- Improved Clear Logs to be faster and more efficient +- Added details view to each command accessable with hold of center button. (Like BLE Spam) +- Made ESP Not Connected screen more helpful with prompts to reboot/reflash if issues persist. +- Renamed CONF menu option to SET to better align with actual Settings menu since it's header is "Settings" and there is a configuration submenu +- Replaced textbox for ESP Connection Check with scrollable Confirmation View + +## v1.0.7 +- Increased buffers and stacks: MAX_BUFFER_SIZE to 8KB, INITIAL_BUFFER_SIZE to 4KB, BUFFER_CLEAR_SIZE to 128B, uart/app stacks to 4KB/6KB +- Added buffer_mutex with proper timeout handling +- Added Marauder-style data handling +- Improved ESP connection reliability +- Added view log from start/end configuration setting +- Added line buffering with overflow detection, boundary protection and pre-flush on mode switches + +## v1.0.7a +- Disable the expansion interface before trying to use UART + +## v1.0.8 + +### 🔴 CRITICAL FIX +- **Fixed PCAP file handling and storage system** + - Resolved critical issue preventing PCAP capture + - Resolved PCAP file stream corruption issues + - Added proper storage system initialization + - Restored PCAP capture functionality + +### 🔄 Improvements +- Command history now persists when exiting to menu +- Added error checking for storage operations + +## TODO +- Replaced select a utility text with prompt to show NEW Help Menu +- IMPROVE optional filtering to UART output +- Improve directory organisation!!!!!!!!!!!!!!!!!!!!!!!!!!!! \ No newline at end of file From 46945bfc53640af266827524977e93935bb18158 Mon Sep 17 00:00:00 2001 From: jay candel Date: Sun, 3 Nov 2024 01:17:26 +0800 Subject: [PATCH 2/5] Delete changelog.md --- changelog.md | 82 ---------------------------------------------------- 1 file changed, 82 deletions(-) delete mode 100644 changelog.md diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 3b39aea..0000000 --- a/changelog.md +++ /dev/null @@ -1,82 +0,0 @@ -# Changelog - -## v1.0.1 -- Revamped menu structure with logical grouping (scanning, beacon spam, attacks, etc.) -- Simplified command addition and cleaned up documentation in `menu.c` -- Centralized and enum-based settings metadata for improved validation and extensibility -- Enhanced settings with Stop-on-Back feature and ESP reboot command -- Added ESP connection verification and clearer error messaging -- Enabled automatic connectivity check and error recovery for ESP issues -- Unified UI with metadata-driven consistency and better type safety -- Simplified UI view switching and improved error display -- Refined code organization, separating concerns, removing redundancy, and standardizing error handling - -## v1.0.2 -- Added confirmation dialogs for WebUI-dependent features in the UI -- Improved settings menu with actions submenu, NVS clearing, and log clearing -- Enhanced memory management and improved settings storage/loading robustness -- Added contextual help for WebUI configuration and confirmation dialogs for command safety -- Improved view navigation, state management, and memory cleanup processes -- Added safeguards against `furi_check` failures with NULL checks and memory initialization - -## v1.0.3 -- Enhanced confirmation view structure and readability with better text alignment -- Added confirmation for "Clear Log Files" with a permanent action warning -- Enabled back press exit on confirmation views with callback context handling -- Improved memory management with context cleanup, view state tracking, and transition fixes -- Added NULL checks, fixed memory leaks, and added state tracking for dialogs - -## v1.0.4 -- Refined confirmation view line breaks for readability -- Improved ESP Connectity check to decrease false negatives -- Added optional filtering to UART output to improve readability (BETA) -- Added 'App Info' Button in Settings -- Misc Changes (mostly to UI) - -## v1.0.5 -- Commands will silently fail if UART isn't working rather than crashing -- Fixed double-free memory issue by removing stream buffer cleanup from the worker thread -- Reorganized initialization order -- UART initialization happens in background -- Serial operations don't block app startup -- Optimized storage initialization by deferring file operations until needed -- Improved directory creation efficiency in storage handling - -## v1.0.6 -- Replaced 'Info' command in ESP Check with 'Stop' -- Slightly improved optional UART filtering -- Memory safety improvements. -- Improved Clear Logs to be faster and more efficient -- Added details view to each command accessable with hold of center button. (Like BLE Spam) -- Made ESP Not Connected screen more helpful with prompts to reboot/reflash if issues persist. -- Renamed CONF menu option to SET to better align with actual Settings menu since it's header is "Settings" and there is a configuration submenu -- Replaced textbox for ESP Connection Check with scrollable Confirmation View - -## v1.0.7 -- Increased buffers and stacks: MAX_BUFFER_SIZE to 8KB, INITIAL_BUFFER_SIZE to 4KB, BUFFER_CLEAR_SIZE to 128B, uart/app stacks to 4KB/6KB -- Added buffer_mutex with proper timeout handling -- Added Marauder-style data handling -- Improved ESP connection reliability -- Added view log from start/end configuration setting -- Added line buffering with overflow detection, boundary protection and pre-flush on mode switches - -## v1.0.7a -- Disable the expansion interface before trying to use UART - -## v1.0.8 - -### 🔴 CRITICAL FIX -- **Fixed PCAP file handling and storage system** - - Resolved critical issue preventing PCAP capture - - Resolved PCAP file stream corruption issues - - Added proper storage system initialization - - Restored PCAP capture functionality - -### 🔄 Improvements -- Command history now persists when exiting to menu -- Added error checking for storage operations - -## TODO -- Replaced select a utility text with prompt to show NEW Help Menu -- IMPROVE optional filtering to UART output -- Improve directory organisation!!!!!!!!!!!!!!!!!!!!!!!!!!!! \ No newline at end of file From c3f41dceef6e0096752b6bcf8640e1134ce70dcc Mon Sep 17 00:00:00 2001 From: jay candel Date: Sun, 3 Nov 2024 01:17:37 +0800 Subject: [PATCH 3/5] Add files via upload --- docs/changelog.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index ee40a65..3b39aea 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -63,6 +63,19 @@ ## v1.0.7a - Disable the expansion interface before trying to use UART +## v1.0.8 + +### 🔴 CRITICAL FIX +- **Fixed PCAP file handling and storage system** + - Resolved critical issue preventing PCAP capture + - Resolved PCAP file stream corruption issues + - Added proper storage system initialization + - Restored PCAP capture functionality + +### 🔄 Improvements +- Command history now persists when exiting to menu +- Added error checking for storage operations + ## TODO - Replaced select a utility text with prompt to show NEW Help Menu - IMPROVE optional filtering to UART output From e8292df6a512e881727e02e4a2629d18ef22d319 Mon Sep 17 00:00:00 2001 From: jay candel Date: Sun, 3 Nov 2024 01:20:01 +0800 Subject: [PATCH 4/5] Add files via upload --- docs/changelog.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 3b39aea..c9ae1bb 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -65,14 +65,13 @@ ## v1.0.8 -### 🔴 CRITICAL FIX -- **Fixed PCAP file handling and storage system** - - Resolved critical issue preventing PCAP capture +### 🔴 CRITICAL FIX - PCAP capture + - Fixed PCAP file handling and storage system - Resolved PCAP file stream corruption issues - Added proper storage system initialization - - Restored PCAP capture functionality + - Restored PCAP capture functionality (yes i promise i fixed it) -### 🔄 Improvements +### Improvements - Command history now persists when exiting to menu - Added error checking for storage operations From 985867a95f4b2d5bbc9adeaee4cbb8d5a1a3b754 Mon Sep 17 00:00:00 2001 From: jay candel Date: Sun, 3 Nov 2024 08:56:22 +0800 Subject: [PATCH 5/5] v1.0.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### 🔴 CRITICAL FIX - PCAP capture - Fixed PCAP file handling and storage system - Resolved PCAP file stream corruption issues - Added proper storage system initialization - Removed the line buffering logic for PCAP data ### Improvements - Added error checking for storage operations - Filtering majorly improved - Improved stop on back to be much more reliable by added type-specific stop commands with delays between operations --- callbacks.c | 6 +- docs/changelog.md | 5 +- menu.c | 61 +++++++++--- settings_ui.c | 2 +- uart_storage.c | 115 +++++++++++++++------- uart_storage.h | 1 - uart_utils.c | 243 +++++++++++++++++++++------------------------- uart_utils.h | 5 +- 8 files changed, 242 insertions(+), 196 deletions(-) diff --git a/callbacks.c b/callbacks.c index fa57968..2a2f763 100644 --- a/callbacks.c +++ b/callbacks.c @@ -203,11 +203,7 @@ void show_app_info(void* context) { FURI_LOG_D("AppInfo", "Show app info called, context: %p", app); const char* info_text = - "Ghost ESP v1.0.5\n\n" - "Created by: Spooky\n" - "Special Thanks:\n" - "- Jay Candel\n" - "Built with <3"; + ""; if(app && app->confirmation_view) { // Create a new context for the confirmation dialog diff --git a/docs/changelog.md b/docs/changelog.md index c9ae1bb..22a6e1d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -69,11 +69,12 @@ - Fixed PCAP file handling and storage system - Resolved PCAP file stream corruption issues - Added proper storage system initialization - - Restored PCAP capture functionality (yes i promise i fixed it) + - Removed the line buffering logic for PCAP data ### Improvements -- Command history now persists when exiting to menu - Added error checking for storage operations +- Filtering majorly improved +- Improved stop on back to be much more reliable by added type-specific stop commands with delays between operations ## TODO - Replaced select a utility text with prompt to show NEW Help Menu diff --git a/menu.c b/menu.c index a905646..f6d20e1 100644 --- a/menu.c +++ b/menu.c @@ -816,18 +816,15 @@ void submenu_callback(void* context, uint32_t index) { bool back_event_callback(void* context) { AppState* state = (AppState*)context; - - // Get the current view ID uint32_t current_view = state->current_view; - // Do not consume the back button event if the current view is the confirmation view - if(current_view == 7) { // 7 is the ID for the confirmation view - // Allow the confirmation view's input callback to handle the back button + // Allow confirmation view to handle its own back button + if(current_view == 7) { return false; } if(current_view == 5) { // Text box view - FURI_LOG_D("Ghost ESP", "Stopping Thread"); + FURI_LOG_D("Ghost ESP", "Stopping Operations"); // Cleanup text buffer if(state->textBoxBuffer) { @@ -839,20 +836,53 @@ bool back_event_callback(void* context) { state->buffer_length = 0; } - // Only send stop commands if enabled in settings + // Send stop commands if enabled in settings if(state->settings.stop_on_back_index) { - // Send all relevant stop commands + // First stop any packet captures to ensure proper file saving + send_uart_command("capture -stop\n", state); + furi_delay_ms(100); // Give time for file operation + + // Reset PCAP state if needed + if(state->uart_context->pcap) { + state->uart_context->pcap = false; + furi_stream_buffer_reset(state->uart_context->pcap_stream); + furi_delay_ms(50); // Allow buffer cleanup + } + + // Then stop various operations in a logical order + send_uart_command("stopscan\n", state); + furi_delay_ms(50); + + send_uart_command("stopspam\n", state); + furi_delay_ms(50); + + send_uart_command("stopdeauth\n", state); + furi_delay_ms(50); + + send_uart_command("stopportal\n", state); + furi_delay_ms(50); + + send_uart_command("blescan -s\n", state); + furi_delay_ms(50); + + // Final general stop send_uart_command("stop\n", state); + furi_delay_ms(50); } - // Close any open files - if(state->uart_context->storageContext->current_file && - storage_file_is_open(state->uart_context->storageContext->current_file)) { - state->uart_context->storageContext->HasOpenedFile = false; - FURI_LOG_D("DEBUG", "Storage File Closed"); + // Close any open files with proper checking + if(state->uart_context->storageContext) { + if(state->uart_context->storageContext->current_file && + storage_file_is_open(state->uart_context->storageContext->current_file)) { + // Give time for final writes + furi_delay_ms(100); + storage_file_close(state->uart_context->storageContext->current_file); + state->uart_context->storageContext->HasOpenedFile = false; + FURI_LOG_D("DEBUG", "Storage File Closed"); + } } - // Return to previous view + // Return to appropriate previous view switch(state->previous_view) { case 1: show_wifi_menu(state); break; case 2: show_ble_menu(state); break; @@ -860,7 +890,7 @@ bool back_event_callback(void* context) { default: show_main_menu(state); break; } state->current_view = state->previous_view; - } else if(current_view == 8) { // Settings actions menu + } else if(current_view == 8) { // Settings menu show_main_menu(state); state->current_view = 0; } else if(current_view != 0) { @@ -870,7 +900,6 @@ bool back_event_callback(void* context) { view_dispatcher_stop(state->view_dispatcher); } - // Consume the back button event for all views except the confirmation view return true; } diff --git a/settings_ui.c b/settings_ui.c index a2bd615..7424b64 100644 --- a/settings_ui.c +++ b/settings_ui.c @@ -391,7 +391,7 @@ bool settings_custom_event_callback(void* context, uint32_t event_id) { "Updated by: Jay Candel\n" "Built with <3"; - confirmation_view_set_header(app_state->confirmation_view, "Ghost ESP v1.0.7a"); + confirmation_view_set_header(app_state->confirmation_view, "Ghost ESP v1.0.8"); confirmation_view_set_text(app_state->confirmation_view, info_text); // Save current view before switching diff --git a/uart_storage.c b/uart_storage.c index 22c9c53..f2c83bf 100644 --- a/uart_storage.c +++ b/uart_storage.c @@ -6,41 +6,64 @@ #include #include "sequential_file.h" - #define COMMAND_BUFFER_SIZE 128 +#define PCAP_WRITE_CHUNK_SIZE 1024u void uart_storage_rx_callback(uint8_t *buf, size_t len, void *context) { UartContext *app = context; - if(app->storageContext->HasOpenedFile) { - storage_file_write(app->storageContext->current_file, buf, len); + + if(!app || !app->storageContext || !app->storageContext->storage_api) { + FURI_LOG_E("Storage", "Invalid storage context"); + return; + } + + if(!app->storageContext->HasOpenedFile || + !app->storageContext->current_file || + !storage_file_is_open(app->storageContext->current_file)) { + FURI_LOG_W("Storage", "No file open for writing"); + app->pcap = false; // Disable PCAP mode if file isn't ready + return; } -} -UartStorageContext *uart_storage_init(UartContext *parentContext) { + // Write in chunks to avoid buffer overflow + size_t written = 0; + while(written < len) { + size_t remaining = len - written; + size_t chunk_size = (remaining < PCAP_WRITE_CHUNK_SIZE) ? + remaining : PCAP_WRITE_CHUNK_SIZE; + + uint16_t bytes_written = storage_file_write( + app->storageContext->current_file, + buf + written, + chunk_size); + + if(bytes_written != chunk_size) { + FURI_LOG_E("Storage", "Write failed: %u/%zu bytes", bytes_written, chunk_size); + app->pcap = false; // Disable PCAP mode on write failure + break; + } + written += bytes_written; + } +} +UartStorageContext* uart_storage_init(UartContext* parentContext) { uint32_t start_time = furi_get_tick(); FURI_LOG_D("Storage", "Starting storage initialization"); - UartStorageContext *ctx = malloc(sizeof(UartStorageContext)); + UartStorageContext* ctx = malloc(sizeof(UartStorageContext)); if(!ctx) { FURI_LOG_E("Storage", "Failed to allocate context"); return NULL; } - memset(ctx, 0, sizeof(UartStorageContext)); ctx->parentContext = parentContext; - // Open storage API - uint32_t storage_open_start = furi_get_tick(); ctx->storage_api = furi_record_open(RECORD_STORAGE); - FURI_LOG_D("Storage", "Storage API open took %lums", furi_get_tick() - storage_open_start); - if(!ctx->storage_api) { FURI_LOG_E("Storage", "Failed to open storage API"); free(ctx); return NULL; } - // Allocate file handles ctx->current_file = storage_file_alloc(ctx->storage_api); ctx->log_file = storage_file_alloc(ctx->storage_api); @@ -53,69 +76,87 @@ UartStorageContext *uart_storage_init(UartContext *parentContext) { return NULL; } - // Create directories efficiently - uint32_t dir_start = furi_get_tick(); - storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER); - storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_LOGS); - storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_PCAPS); - storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_WARDRIVE); - FURI_LOG_D("Storage", "Directory creation took %lums", furi_get_tick() - dir_start); + // Create directories with verification + if(!storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER)) { + FURI_LOG_W("Storage", "Failed to create app folder"); + } + if(!storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_PCAPS)) { + FURI_LOG_W("Storage", "Failed to create PCAP folder"); + } + if(!storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_LOGS)) { + FURI_LOG_W("Storage", "Failed to create logs folder"); + } + if(!storage_simply_mkdir(ctx->storage_api, GHOST_ESP_APP_FOLDER_WARDRIVE)) { + FURI_LOG_W("Storage", "Failed to create wardrive folder"); + } + + // Verify PCAP directory exists and is writable + File* test_dir = storage_file_alloc(ctx->storage_api); + if(test_dir) { + if(!storage_dir_open(test_dir, GHOST_ESP_APP_FOLDER_PCAPS)) { + FURI_LOG_E("Storage", "PCAP directory not accessible"); + } + storage_dir_close(test_dir); + storage_file_free(test_dir); + } - // Initialize log file efficiently - uint32_t log_start = furi_get_tick(); + // Initialize log file bool log_ok = sequential_file_open( ctx->storage_api, ctx->log_file, GHOST_ESP_APP_FOLDER_LOGS, "ghost_logs", "txt"); - + if(!log_ok) { - FURI_LOG_W("Storage", "Failed to create initial log file"); + FURI_LOG_E("Storage", "Failed to open log file"); } - FURI_LOG_D("Storage", "Log file creation took %lums", furi_get_tick() - log_start); ctx->HasOpenedFile = log_ok; + ctx->IsWritingToFile = false; FURI_LOG_I("Storage", "Storage initialization completed in %lums", furi_get_tick() - start_time); return ctx; } + void uart_storage_reset_logs(UartStorageContext *ctx) { if(!ctx || !ctx->storage_api) return; - FURI_LOG_D("Storage", "Resetting log files"); - - // Close existing log file if open if(ctx->log_file) { storage_file_close(ctx->log_file); storage_file_free(ctx->log_file); ctx->log_file = storage_file_alloc(ctx->storage_api); } - // Create new log file ctx->HasOpenedFile = sequential_file_open( ctx->storage_api, ctx->log_file, GHOST_ESP_APP_FOLDER_LOGS, "ghost_logs", "txt"); - + if(!ctx->HasOpenedFile) { - FURI_LOG_E("Storage", "Failed to create new log file during reset"); + FURI_LOG_E("Storage", "Failed to reset log file"); } } + void uart_storage_free(UartStorageContext *ctx) { if(!ctx) return; - uint32_t start_time = furi_get_tick(); - FURI_LOG_D("Storage", "Starting storage cleanup"); + if(ctx->current_file) { + storage_file_close(ctx->current_file); + storage_file_free(ctx->current_file); + } - if(ctx->current_file) storage_file_free(ctx->current_file); - if(ctx->log_file) storage_file_free(ctx->log_file); - if(ctx->storage_api) furi_record_close(RECORD_STORAGE); + if(ctx->log_file) { + storage_file_close(ctx->log_file); + storage_file_free(ctx->log_file); + } + + if(ctx->storage_api) { + furi_record_close(RECORD_STORAGE); + } free(ctx); - FURI_LOG_D("Storage", "Storage cleanup completed in %lums", - furi_get_tick() - start_time); } \ No newline at end of file diff --git a/uart_storage.h b/uart_storage.h index 4c9ed3f..65f04e8 100644 --- a/uart_storage.h +++ b/uart_storage.h @@ -4,7 +4,6 @@ #include #include - struct UartStorageContext { Storage* storage_api; File* current_file; diff --git a/uart_utils.c b/uart_utils.c index 94176c3..875b837 100644 --- a/uart_utils.c +++ b/uart_utils.c @@ -7,7 +7,7 @@ #include #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone | WorkerEvtPcapDone) - +#define PCAP_WRITE_CHUNK_SIZE 1024 #define AP_LIST_TIMEOUT_MS 5000 #define INITIAL_BUFFER_SIZE 2048 #define BUFFER_GROWTH_FACTOR 1.5 @@ -42,102 +42,52 @@ static bool init_buffer_mutex() { static void uart_rx_callback(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { UartContext* uart = (UartContext*)context; - static uint8_t rx_buf[256]; // Increased buffer size further for safety - static size_t rx_buf_pos = 0; if(event == FuriHalSerialRxEventData) { uint8_t data = furi_hal_serial_async_rx(handle); const char* mark_begin = "[BUF/BEGIN]"; const char* mark_close = "[BUF/CLOSE]"; - bool data_handled = false; - - // Handle marker detection first - if(uart->mark_test_idx > 0) { - if(uart->mark_test_idx < sizeof(uart->mark_test_buf) - 1) { - // Still collecting potential marker - if(data == mark_begin[uart->mark_test_idx] || - data == mark_close[uart->mark_test_idx]) { - uart->mark_test_buf[uart->mark_test_idx++] = data; - if(uart->mark_test_idx == 11) { - // Complete marker - check type and flush buffer first - if(rx_buf_pos > 0) { - size_t sent = furi_stream_buffer_send(uart->rx_stream, rx_buf, rx_buf_pos, 0); - if(sent != rx_buf_pos) { - FURI_LOG_E("UART", "Buffer overflow - lost %d bytes", rx_buf_pos - sent); - } - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); - rx_buf_pos = 0; - } - - if(!memcmp(uart->mark_test_buf, mark_begin, 11)) { - uart->pcap = true; - } else if(!memcmp(uart->mark_test_buf, mark_close, 11)) { - uart->pcap = false; - } - uart->mark_test_idx = 0; - } - data_handled = true; - } else { - // Marker mismatch - add to appropriate buffer - if(uart->pcap) { - size_t sent = furi_stream_buffer_send(uart->pcap_stream, uart->mark_test_buf, - uart->mark_test_idx, 0); - if(sent != uart->mark_test_idx) { - FURI_LOG_E("UART", "PCAP buffer overflow - lost %d bytes", - uart->mark_test_idx - sent); - } - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), - WorkerEvtPcapDone); - } else { - // Add to line buffer - for(size_t i = 0; i < uart->mark_test_idx; i++) { - if(rx_buf_pos < sizeof(rx_buf)) { - rx_buf[rx_buf_pos++] = uart->mark_test_buf[i]; - } - } + + if(uart->mark_test_idx != 0) { + if(data == mark_begin[uart->mark_test_idx] || + data == mark_close[uart->mark_test_idx]) { + uart->mark_test_buf[uart->mark_test_idx++] = data; + + if(uart->mark_test_idx == sizeof(uart->mark_test_buf)) { + if(!memcmp(uart->mark_test_buf, (void*)mark_begin, sizeof(uart->mark_test_buf))) { + uart->pcap = true; + } else if(!memcmp(uart->mark_test_buf, (void*)mark_close, sizeof(uart->mark_test_buf))) { + uart->pcap = false; } uart->mark_test_idx = 0; } + return; } else { - // Buffer overflow protection + if(uart->pcap) { + furi_stream_buffer_send(uart->pcap_stream, uart->mark_test_buf, uart->mark_test_idx, 0); + furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtPcapDone); + } else { + furi_stream_buffer_send(uart->rx_stream, uart->mark_test_buf, uart->mark_test_idx, 0); + furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); + } uart->mark_test_idx = 0; } } - // Handle start of new marker - if(!data_handled && data == mark_begin[0]) { - uart->mark_test_buf[0] = data; - uart->mark_test_idx = 1; - data_handled = true; - } - - // Handle regular data - if(!data_handled) { + if(data == mark_begin[0]) { + uart->mark_test_buf[uart->mark_test_idx++] = data; + } else { if(uart->pcap) { - size_t sent = furi_stream_buffer_send(uart->pcap_stream, &data, 1, 0); - if(sent != 1) { - FURI_LOG_E("UART", "PCAP buffer overflow - lost byte"); - } + furi_stream_buffer_send(uart->pcap_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtPcapDone); } else { - // Add to line buffer - if(rx_buf_pos < sizeof(rx_buf)) { - rx_buf[rx_buf_pos++] = data; - } - - // Send buffer when we have a complete line or buffer is getting full - if(data == '\n' || rx_buf_pos >= (sizeof(rx_buf) * 3/4)) { - size_t sent = furi_stream_buffer_send(uart->rx_stream, rx_buf, rx_buf_pos, 0); - if(sent != rx_buf_pos) { - FURI_LOG_E("UART", "Buffer overflow - lost %d bytes", rx_buf_pos - sent); - } - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); - rx_buf_pos = 0; - } + furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); + furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); } } } } + static bool process_chunk(LineProcessingState* state, const char* input, char* output, size_t output_size, size_t* output_len) { @@ -689,50 +639,52 @@ void handle_uart_rx_data(uint8_t *buf, size_t len, void *context) { furi_mutex_release(buffer_mutex); } // UART worker thread function -static int32_t uart_worker(void *context) { - UartContext *uart = (void *)context; - uint8_t line_buf[RX_BUF_SIZE]; - size_t line_pos = 0; - - while (1) { - uint32_t events = furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); +static int32_t uart_worker(void* context) { + UartContext* uart = (void*)context; + + while(1) { + uint32_t events = furi_thread_flags_wait( + WORKER_ALL_RX_EVENTS, + FuriFlagWaitAny, + FuriWaitForever); + furi_check((events & FuriFlagError) == 0); - if (events & WorkerEvtStop) break; + if(events & WorkerEvtStop) break; - if (events & WorkerEvtRxDone) { - size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0); - - if (len > 0) { - // Process received data - for(size_t i = 0; i < len; i++) { - if(line_pos < sizeof(line_buf) - 1) { - line_buf[line_pos++] = uart->rx_buf[i]; - } - - // If we hit a newline or buffer is full, process the line - if(uart->rx_buf[i] == '\n' || line_pos >= sizeof(line_buf) - 1) { - line_buf[line_pos] = '\0'; - - if (uart->handle_rx_data_cb) - uart->handle_rx_data_cb(line_buf, line_pos, uart->state); - - line_pos = 0; - } - } + if(events & WorkerEvtRxDone) { + size_t len = furi_stream_buffer_receive( + uart->rx_stream, + uart->rx_buf, + RX_BUF_SIZE, + 0); + + if(len > 0) { + if(uart->handle_rx_data_cb) + uart->handle_rx_data_cb(uart->rx_buf, len, uart->state); } } - if (events & WorkerEvtPcapDone) { - size_t len = furi_stream_buffer_receive(uart->pcap_stream, uart->rx_buf, RX_BUF_SIZE, 0); - if (len > 0) { - if (uart->handle_rx_pcap_cb) + if(events & WorkerEvtPcapDone) { + size_t len = furi_stream_buffer_receive( + uart->pcap_stream, + uart->rx_buf, + RX_BUF_SIZE, + 0); + + if(len > 0) { + if(uart->handle_rx_pcap_cb) uart->handle_rx_pcap_cb(uart->rx_buf, len, uart); } } } + + furi_stream_buffer_free(uart->rx_stream); + furi_stream_buffer_free(uart->pcap_stream); + return 0; } + void update_text_box_view(AppState* state) { if(!state || !state->text_box || !state->textBoxBuffer) return; @@ -875,29 +827,7 @@ void uart_send(UartContext *uart, const uint8_t *data, size_t len) { furi_hal_serial_tx(uart->serial_handle, data, len); } } -void uart_receive_data( - UartContext *uart, - ViewDispatcher *view_dispatcher, - AppState *state, - const char *prefix, - const char *extension, - const char *TargetFolder) -{ - UNUSED(uart); - text_box_set_text(state->text_box, ""); - text_box_set_focus(state->text_box, TextBoxFocusEnd); - if (strlen(prefix) > 1) - { - uart->storageContext->HasOpenedFile = sequential_file_open( - uart->storageContext->storage_api, - uart->storageContext->current_file, - TargetFolder, - prefix, - extension); - } - view_dispatcher_switch_to_view(view_dispatcher, 5); - state->current_view = 5; -} + bool uart_is_esp_connected(UartContext* uart) { FURI_LOG_D("UART", "Checking ESP connection..."); @@ -985,4 +915,53 @@ bool uart_is_esp_connected(UartContext* uart) { } return connected; +} +void uart_receive_data( + UartContext* uart, + ViewDispatcher* view_dispatcher, + AppState* state, + const char* prefix, + const char* extension, + const char* TargetFolder) { + + if(!uart || !uart->storageContext || !view_dispatcher || !state || !prefix || !extension || !TargetFolder) { + FURI_LOG_E("UART", "Invalid parameters in uart_receive_data"); + return; + } + + // Safely disable PCAP mode if active + if(uart->pcap) { + uart->pcap = false; + furi_delay_ms(10); // Allow buffers to flush + if(uart->pcap_stream) { + furi_stream_buffer_reset(uart->pcap_stream); + } + } + + text_box_set_text(state->text_box, ""); + text_box_set_focus(state->text_box, TextBoxFocusEnd); + + if(strlen(prefix) > 1) { + // Close any existing file first + if(uart->storageContext->HasOpenedFile && uart->storageContext->current_file) { + storage_file_close(uart->storageContext->current_file); + uart->storageContext->HasOpenedFile = false; + } + + // Open new file with proper error handling + uart->storageContext->HasOpenedFile = sequential_file_open( + uart->storageContext->storage_api, + uart->storageContext->current_file, + TargetFolder, + prefix, + extension); + + if(!uart->storageContext->HasOpenedFile) { + FURI_LOG_E("UART", "Failed to open file for writing"); + return; + } + } + + view_dispatcher_switch_to_view(view_dispatcher, 5); + state->current_view = 5; } \ No newline at end of file diff --git a/uart_utils.h b/uart_utils.h index 25fb2b1..7bd814c 100644 --- a/uart_utils.h +++ b/uart_utils.h @@ -11,8 +11,9 @@ #include "menu.h" #include "uart_storage.h" #define TEXT_BOX_STORE_SIZE (4096) // 4KB text box buffer size - -#define RX_BUF_SIZE 256 +#define RX_BUF_SIZE 1024 +#define PCAP_BUF_SIZE 4096 +#define STORAGE_BUF_SIZE 4096 #define GHOST_ESP_APP_FOLDER "/ext/apps_data/ghost_esp" #define GHOST_ESP_APP_FOLDER_PCAPS "/ext/apps_data/ghost_esp/pcaps" #define GHOST_ESP_APP_FOLDER_WARDRIVE "/ext/apps_data/ghost_esp/wardrive"