|
|
@@ -153,22 +153,26 @@ static void get_timeout_timer_callback(void *context)
|
|
|
}
|
|
|
|
|
|
static void flipper_http_rx_callback(const char *line, void *context); // forward declaration
|
|
|
+// Instead of two globals, we use a single static pointer to the active instance.
|
|
|
+static FlipperHTTP *active_fhttp = NULL;
|
|
|
|
|
|
-// UART initialization function
|
|
|
-/**
|
|
|
- * @brief Initialize UART.
|
|
|
- * @return FlipperHTTP context if the UART was initialized successfully, NULL otherwise.
|
|
|
- * @note The received data will be handled asynchronously via the callback.
|
|
|
- */
|
|
|
FlipperHTTP *flipper_http_alloc()
|
|
|
{
|
|
|
- FlipperHTTP *fhttp = (FlipperHTTP *)malloc(sizeof(FlipperHTTP));
|
|
|
+ // If an active instance already exists, free it first.
|
|
|
+ if (active_fhttp != NULL)
|
|
|
+ {
|
|
|
+ FURI_LOG_E(HTTP_TAG, "Existing UART instance detected, freeing previous instance.");
|
|
|
+ flipper_http_free(active_fhttp);
|
|
|
+ active_fhttp = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ FlipperHTTP *fhttp = malloc(sizeof(FlipperHTTP));
|
|
|
if (!fhttp)
|
|
|
{
|
|
|
FURI_LOG_E(HTTP_TAG, "Failed to allocate FlipperHTTP.");
|
|
|
return NULL;
|
|
|
}
|
|
|
- memset(fhttp, 0, sizeof(FlipperHTTP)); // Initialize allocated memory to zero
|
|
|
+ memset(fhttp, 0, sizeof(FlipperHTTP));
|
|
|
|
|
|
fhttp->flipper_http_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
|
|
|
if (!fhttp->flipper_http_stream)
|
|
|
@@ -189,7 +193,7 @@ FlipperHTTP *flipper_http_alloc()
|
|
|
|
|
|
furi_thread_set_name(fhttp->rx_thread, "FlipperHTTP_RxThread");
|
|
|
furi_thread_set_stack_size(fhttp->rx_thread, 1024);
|
|
|
- furi_thread_set_context(fhttp->rx_thread, fhttp); // Corrected context
|
|
|
+ furi_thread_set_context(fhttp->rx_thread, fhttp);
|
|
|
furi_thread_set_callback(fhttp->rx_thread, flipper_http_worker);
|
|
|
|
|
|
fhttp->handle_rx_line_cb = flipper_http_rx_callback;
|
|
|
@@ -198,24 +202,11 @@ FlipperHTTP *flipper_http_alloc()
|
|
|
furi_thread_start(fhttp->rx_thread);
|
|
|
fhttp->rx_thread_id = furi_thread_get_id(fhttp->rx_thread);
|
|
|
|
|
|
- // Handle when the UART control is busy to avoid furi_check failed
|
|
|
- if (furi_hal_serial_control_is_busy(UART_CH))
|
|
|
- {
|
|
|
- FURI_LOG_E(HTTP_TAG, "UART control is busy.");
|
|
|
- // Cleanup resources
|
|
|
- furi_thread_flags_set(fhttp->rx_thread_id, WorkerEvtStop);
|
|
|
- furi_thread_join(fhttp->rx_thread);
|
|
|
- furi_thread_free(fhttp->rx_thread);
|
|
|
- furi_stream_buffer_free(fhttp->flipper_http_stream);
|
|
|
- free(fhttp);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
+ // Acquire UART control
|
|
|
fhttp->serial_handle = furi_hal_serial_control_acquire(UART_CH);
|
|
|
if (!fhttp->serial_handle)
|
|
|
{
|
|
|
FURI_LOG_E(HTTP_TAG, "Failed to acquire UART control - handle is NULL");
|
|
|
- // Cleanup resources
|
|
|
furi_thread_flags_set(fhttp->rx_thread_id, WorkerEvtStop);
|
|
|
furi_thread_join(fhttp->rx_thread);
|
|
|
furi_thread_free(fhttp->rx_thread);
|
|
|
@@ -224,29 +215,17 @@ FlipperHTTP *flipper_http_alloc()
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- // Initialize UART with acquired handle
|
|
|
+ // Initialize and enable UART
|
|
|
furi_hal_serial_init(fhttp->serial_handle, BAUDRATE);
|
|
|
-
|
|
|
- // Enable RX direction
|
|
|
furi_hal_serial_enable_direction(fhttp->serial_handle, FuriHalSerialDirectionRx);
|
|
|
-
|
|
|
- // Start asynchronous RX with the corrected callback and context
|
|
|
- furi_hal_serial_async_rx_start(fhttp->serial_handle, _flipper_http_rx_callback, fhttp, false); // Corrected context
|
|
|
-
|
|
|
- // Wait for the TX to complete to ensure UART is ready
|
|
|
+ furi_hal_serial_async_rx_start(fhttp->serial_handle, _flipper_http_rx_callback, fhttp, false);
|
|
|
furi_hal_serial_tx_wait_complete(fhttp->serial_handle);
|
|
|
|
|
|
- // Allocate the timer for handling timeouts
|
|
|
- fhttp->get_timeout_timer = furi_timer_alloc(
|
|
|
- get_timeout_timer_callback, // Callback function
|
|
|
- FuriTimerTypeOnce, // One-shot timer
|
|
|
- fhttp // Corrected context
|
|
|
- );
|
|
|
-
|
|
|
+ // Allocate the timeout timer
|
|
|
+ fhttp->get_timeout_timer = furi_timer_alloc(get_timeout_timer_callback, FuriTimerTypeOnce, fhttp);
|
|
|
if (!fhttp->get_timeout_timer)
|
|
|
{
|
|
|
FURI_LOG_E(HTTP_TAG, "Failed to allocate HTTP request timeout timer.");
|
|
|
- // Cleanup resources
|
|
|
furi_hal_serial_async_rx_stop(fhttp->serial_handle);
|
|
|
furi_hal_serial_disable_direction(fhttp->serial_handle, FuriHalSerialDirectionRx);
|
|
|
furi_hal_serial_control_release(fhttp->serial_handle);
|
|
|
@@ -258,15 +237,12 @@ FlipperHTTP *flipper_http_alloc()
|
|
|
free(fhttp);
|
|
|
return NULL;
|
|
|
}
|
|
|
-
|
|
|
- // Set the timer thread priority if needed
|
|
|
furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
|
|
|
|
|
|
- fhttp->last_response = (char *)malloc(RX_BUF_SIZE);
|
|
|
+ fhttp->last_response = malloc(RX_BUF_SIZE);
|
|
|
if (!fhttp->last_response)
|
|
|
{
|
|
|
FURI_LOG_E(HTTP_TAG, "Failed to allocate memory for last_response.");
|
|
|
- // Cleanup resources
|
|
|
furi_timer_free(fhttp->get_timeout_timer);
|
|
|
furi_hal_serial_async_rx_stop(fhttp->serial_handle);
|
|
|
furi_hal_serial_disable_direction(fhttp->serial_handle, FuriHalSerialDirectionRx);
|
|
|
@@ -279,21 +255,15 @@ FlipperHTTP *flipper_http_alloc()
|
|
|
free(fhttp);
|
|
|
return NULL;
|
|
|
}
|
|
|
- memset(fhttp->last_response, 0, RX_BUF_SIZE); // Initialize last_response
|
|
|
-
|
|
|
+ memset(fhttp->last_response, 0, RX_BUF_SIZE);
|
|
|
fhttp->state = IDLE;
|
|
|
|
|
|
- // FURI_LOG_I(HTTP_TAG, "UART initialized successfully.");
|
|
|
+ // Track the active instance globally.
|
|
|
+ active_fhttp = fhttp;
|
|
|
+
|
|
|
return fhttp;
|
|
|
}
|
|
|
|
|
|
-// Deinitialize UART
|
|
|
-/**
|
|
|
- * @brief Deinitialize UART.
|
|
|
- * @return void
|
|
|
- * @param fhttp The FlipperHTTP context
|
|
|
- * @note This function will stop the asynchronous RX, release the serial handle, and free the resources.
|
|
|
- */
|
|
|
void flipper_http_free(FlipperHTTP *fhttp)
|
|
|
{
|
|
|
if (!fhttp)
|
|
|
@@ -306,43 +276,42 @@ void flipper_http_free(FlipperHTTP *fhttp)
|
|
|
FURI_LOG_E(HTTP_TAG, "UART handle is NULL. Already deinitialized?");
|
|
|
return;
|
|
|
}
|
|
|
- // Stop asynchronous RX
|
|
|
+ // Stop asynchronous RX and clean up UART
|
|
|
furi_hal_serial_async_rx_stop(fhttp->serial_handle);
|
|
|
-
|
|
|
- // Release and deinitialize the serial handle
|
|
|
furi_hal_serial_disable_direction(fhttp->serial_handle, FuriHalSerialDirectionRx);
|
|
|
- furi_hal_serial_control_release(fhttp->serial_handle);
|
|
|
furi_hal_serial_deinit(fhttp->serial_handle);
|
|
|
+ furi_hal_serial_control_release(fhttp->serial_handle);
|
|
|
|
|
|
- // Signal the worker thread to stop
|
|
|
+ // Signal and free the worker thread
|
|
|
furi_thread_flags_set(fhttp->rx_thread_id, WorkerEvtStop);
|
|
|
- // Wait for the thread to finish
|
|
|
furi_thread_join(fhttp->rx_thread);
|
|
|
- // Free the thread resources
|
|
|
furi_thread_free(fhttp->rx_thread);
|
|
|
|
|
|
// Free the stream buffer
|
|
|
furi_stream_buffer_free(fhttp->flipper_http_stream);
|
|
|
|
|
|
- // Free the timer
|
|
|
+ // Free the timer, if allocated
|
|
|
if (fhttp->get_timeout_timer)
|
|
|
{
|
|
|
furi_timer_free(fhttp->get_timeout_timer);
|
|
|
fhttp->get_timeout_timer = NULL;
|
|
|
}
|
|
|
|
|
|
- // Free the last response
|
|
|
+ // Free the last_response buffer
|
|
|
if (fhttp->last_response)
|
|
|
{
|
|
|
free(fhttp->last_response);
|
|
|
fhttp->last_response = NULL;
|
|
|
}
|
|
|
|
|
|
- // Free the FlipperHTTP context
|
|
|
- free(fhttp);
|
|
|
- fhttp = NULL;
|
|
|
+ // If this instance is the active instance, clear the static pointer.
|
|
|
+ if (active_fhttp == fhttp)
|
|
|
+ {
|
|
|
+ free(active_fhttp);
|
|
|
+ active_fhttp = NULL;
|
|
|
+ }
|
|
|
|
|
|
- // FURI_LOG_I("FlipperHTTP", "UART deinitialized successfully.");
|
|
|
+ free(fhttp);
|
|
|
}
|
|
|
|
|
|
/**
|