mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-27 18:13:44 +02:00
Refactor global state management for startup commands and USB handover (no Race-Condition); enhance SerialManager shutdown process and buffer handling in UVCStream.
This commit is contained in:
@@ -4,15 +4,15 @@
|
||||
// Forward declarations
|
||||
extern void start_video_streaming(void *arg);
|
||||
|
||||
bool startupCommandReceived = false;
|
||||
static bool s_startupCommandReceived = false;
|
||||
bool getStartupCommandReceived()
|
||||
{
|
||||
return startupCommandReceived;
|
||||
return s_startupCommandReceived;
|
||||
}
|
||||
|
||||
void setStartupCommandReceived(bool startupCommandReceived)
|
||||
{
|
||||
startupCommandReceived = startupCommandReceived;
|
||||
s_startupCommandReceived = startupCommandReceived;
|
||||
}
|
||||
|
||||
static TaskHandle_t *g_serial_manager_handle = nullptr;
|
||||
@@ -27,15 +27,15 @@ void setSerialManagerHandle(TaskHandle_t *serialManagerHandle)
|
||||
}
|
||||
|
||||
// Global pause state
|
||||
bool startupPaused = false;
|
||||
static bool s_startupPaused = false;
|
||||
bool getStartupPaused()
|
||||
{
|
||||
return startupPaused;
|
||||
return s_startupPaused;
|
||||
}
|
||||
|
||||
void setStartupPaused(bool startupPaused)
|
||||
{
|
||||
startupPaused = startupPaused;
|
||||
s_startupPaused = startupPaused;
|
||||
}
|
||||
|
||||
// Function to manually activate streaming
|
||||
@@ -47,4 +47,9 @@ void activateStreaming(bool disableSetup)
|
||||
void *serialTaskHandle = (serialHandle && *serialHandle) ? *serialHandle : nullptr;
|
||||
|
||||
start_video_streaming(serialTaskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// USB handover state
|
||||
static bool s_usbHandoverDone = false;
|
||||
bool getUsbHandoverDone() { return s_usbHandoverDone; }
|
||||
void setUsbHandoverDone(bool done) { s_usbHandoverDone = done; }
|
||||
@@ -21,4 +21,8 @@ void setStartupCommandReceived(bool startupCommandReceived);
|
||||
bool getStartupPaused();
|
||||
void setStartupPaused(bool startupPaused);
|
||||
|
||||
// Tracks whether USB handover from usb_serial_jtag to TinyUSB was performed
|
||||
bool getUsbHandoverDone();
|
||||
void setUsbHandoverDone(bool done);
|
||||
|
||||
#endif
|
||||
@@ -24,13 +24,36 @@ void SerialManager::try_receive()
|
||||
int current_position = 0;
|
||||
int len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20);
|
||||
|
||||
// If driver is uninstalled or an error occurs, abort read gracefully
|
||||
if (len < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// since we've got something on the serial port
|
||||
// we gotta keep reading until we've got the whole message
|
||||
while (len)
|
||||
while (len > 0)
|
||||
{
|
||||
memcpy(this->data + current_position, this->temp_data, len);
|
||||
// Prevent buffer overflow
|
||||
if (current_position + len >= BUF_SIZE)
|
||||
{
|
||||
int copy_len = BUF_SIZE - 1 - current_position;
|
||||
if (copy_len > 0)
|
||||
{
|
||||
memcpy(this->data + current_position, this->temp_data, copy_len);
|
||||
current_position += copy_len;
|
||||
}
|
||||
// Drop the rest of the input to avoid overflow
|
||||
break;
|
||||
}
|
||||
memcpy(this->data + current_position, this->temp_data, (size_t)len);
|
||||
current_position += len;
|
||||
len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20);
|
||||
if (len < 0)
|
||||
{
|
||||
// Driver likely uninstalled during handover; stop processing this cycle
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_position)
|
||||
@@ -42,9 +65,10 @@ void SerialManager::try_receive()
|
||||
// Notify main that a command was received during startup
|
||||
notify_startup_command_received();
|
||||
|
||||
const auto result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(this->data)));
|
||||
const auto resultMessage = result.getResult();
|
||||
usb_serial_jtag_write_bytes(resultMessage.c_str(), resultMessage.length(), 1000 / 20);
|
||||
const auto result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(this->data)));
|
||||
const auto resultMessage = result.getResult();
|
||||
int written = usb_serial_jtag_write_bytes(resultMessage.c_str(), resultMessage.length(), 1000 / 20);
|
||||
(void)written; // ignore errors if driver already uninstalled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +103,7 @@ void SerialManager::send_heartbeat()
|
||||
sprintf(heartbeat, "{\"heartbeat\":\"openiris_setup_mode\",\"serial\":\"%s\"}\n", serial_number);
|
||||
|
||||
usb_serial_jtag_write_bytes(heartbeat, strlen(heartbeat), 1000 / 20);
|
||||
// Ignore return value; if the driver was uninstalled, this is a no-op
|
||||
}
|
||||
|
||||
bool SerialManager::should_send_heartbeat()
|
||||
@@ -123,4 +148,19 @@ void HandleSerialManagerTask(void *pvParameters)
|
||||
lastHeartbeat = currentTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SerialManager::shutdown()
|
||||
{
|
||||
// Stop heartbeats; timer will be deleted by main if needed.
|
||||
// Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB.
|
||||
esp_err_t err = usb_serial_jtag_driver_uninstall();
|
||||
if (err == ESP_OK)
|
||||
{
|
||||
ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled");
|
||||
}
|
||||
else if (err != ESP_ERR_INVALID_STATE)
|
||||
{
|
||||
ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
void send_heartbeat();
|
||||
bool should_send_heartbeat();
|
||||
void notify_startup_command_received();
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
std::shared_ptr<CommandManager> commandManager;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "UVCStream/UVCStream.cpp"
|
||||
INCLUDE_DIRS "UVCStream"
|
||||
REQUIRES esp_timer esp32-camera StateManager usb_device_uvc CameraManager
|
||||
REQUIRES esp_timer esp32-camera StateManager usb_device_uvc CameraManager Helpers
|
||||
)
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "UVCStream.hpp"
|
||||
#include <cstdio> // for snprintf
|
||||
#include "driver/usb_serial_jtag.h" // for clean handover from COM to TinyUSB
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
// no deps on main globals here; handover is performed in main before calling setup when needed
|
||||
|
||||
static const char *UVC_STREAM_TAG = "[UVC DEVICE]";
|
||||
|
||||
@@ -33,7 +37,6 @@ extern "C" {
|
||||
|
||||
static esp_err_t UVCStreamHelpers::camera_start_cb(uvc_format_t format, int width, int height, int rate, void *cb_ctx)
|
||||
{
|
||||
auto *mgr = static_cast<UVCStreamManager *>(cb_ctx);
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Camera Start");
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Format: %d, width: %d, height: %d, rate: %d", format, width, height, rate);
|
||||
framesize_t frame_size = FRAMESIZE_QVGA;
|
||||
@@ -79,6 +82,7 @@ static void UVCStreamHelpers::camera_stop_cb(void *cb_ctx)
|
||||
static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
|
||||
{
|
||||
auto *mgr = static_cast<UVCStreamManager *>(cb_ctx);
|
||||
(void)mgr;
|
||||
s_fb.cam_fb_p = esp_camera_fb_get();
|
||||
|
||||
if (!s_fb.cam_fb_p)
|
||||
|
||||
Reference in New Issue
Block a user