#include "cmd_transport.h" #include "esp_log.h" #include "esp_console.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/soc_caps.h" #include #include #include #if SOC_USB_SERIAL_JTAG_SUPPORTED #include "driver/usb_serial_jtag.h" #endif static const char *TAG = "CMD_TP"; #define MAX_LISTENERS 4 static cmd_line_handler_t s_listeners[MAX_LISTENERS] = {0}; static int s_listener_count = 0; static bool s_inited = false; void cmd_transport_register_listener(cmd_line_handler_t handler) { if (s_listener_count < MAX_LISTENERS) { s_listeners[s_listener_count++] = handler; } } // Trim trailing whitespace (CR, LF) static void trim_trailing(char *s) { int n = strlen(s); while (n > 0 && (s[n-1] == '\r' || s[n-1] == '\n' || isspace((unsigned char)s[n-1]))) { s[--n] = 0; } } // Dispatch line to listeners, then to ESP Console static void dispatch_line(char *line, cmd_reply_func_t reply_func, void *reply_ctx) { bool handled = false; // 1. Offer to registered listeners (e.g. wifi_cfg) for (int i = 0; i < s_listener_count; i++) { if (s_listeners[i] && s_listeners[i](line, reply_func, reply_ctx)) { handled = true; break; } } // 2. If not handled, pass to system console (for commands like 'mode_monitor') if (!handled && strlen(line) > 0) { int ret; esp_err_t err = esp_console_run(line, &ret); if (err == ESP_ERR_NOT_FOUND) { // Unrecognized command - silent ignore or reply error } else if (err != ESP_OK) { ESP_LOGE(TAG, "Console run error: %s", esp_err_to_name(err)); } } } // --- UART (stdin/stdout) Support --- static void uart_reply(const char *msg, void *ctx) { (void)ctx; printf("%s", msg); fflush(stdout); } static void uart_listener_task(void *arg) { char line[256]; // Disable buffering setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); while (1) { if (fgets(line, sizeof(line), stdin)) { trim_trailing(line); dispatch_line(line, uart_reply, NULL); } else { vTaskDelay(pdMS_TO_TICKS(20)); } } } // --- USB Serial/JTAG Support --- #if SOC_USB_SERIAL_JTAG_SUPPORTED static void usb_reply(const char *msg, void *ctx) { (void)ctx; usb_serial_jtag_write_bytes((const uint8_t*)msg, strlen(msg), pdMS_TO_TICKS(50)); } static void usb_listener_task(void *arg) { usb_serial_jtag_driver_config_t d = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); if (usb_serial_jtag_driver_install(&d) != ESP_OK) { ESP_LOGE(TAG, "Failed to install USB-Serial/JTAG driver"); vTaskDelete(NULL); } char buf[256]; size_t idx = 0; uint8_t c; while (1) { int n = usb_serial_jtag_read_bytes(&c, 1, pdMS_TO_TICKS(20)); if (n > 0) { if (c == '\n' || c == '\r') { if (idx > 0) { buf[idx] = 0; dispatch_line(buf, usb_reply, NULL); idx = 0; } } else { if (idx < sizeof(buf) - 1) { buf[idx++] = (char)c; } } } } } #endif void cmd_transport_init(void) { if (s_inited) return; s_inited = true; // Start UART Listener xTaskCreatePinnedToCore(uart_listener_task, "cmd_uart", 4096, NULL, 5, NULL, tskNO_AFFINITY); // Start USB Listener (if supported) #if SOC_USB_SERIAL_JTAG_SUPPORTED xTaskCreatePinnedToCore(usb_listener_task, "cmd_usb", 4096, NULL, 5, NULL, tskNO_AFFINITY); #endif }