#include "host_transport.h" #include "cmd_handler.h" #include "esp_log.h" #include "uart.h" #include "uart_messages.pb.h" #include #include static const char *TAG = "[HOST]"; static host_tx_fn_t s_tx_fn; static QueueHandle_t s_cmd_queue; static uart_packet_t s_rx_packet = {.state = STATE_START}; static TickType_t s_last_byte_ticks; static const TickType_t s_rx_timeout_ticks = pdMS_TO_TICKS(50); void host_transport_set_tx(host_tx_fn_t tx_fn) { s_tx_fn = tx_fn; } void host_transport_set_cmd_queue(QueueHandle_t cmd_queue) { s_cmd_queue = cmd_queue; } QueueHandle_t host_transport_cmd_queue(void) { return s_cmd_queue; } bool host_enqueue_packet(const uint8_t *payload, uint8_t len) { if (s_cmd_queue == NULL || payload == NULL || len == 0) { return false; } generic_msg_t msg = { .msg_id = payload[0], .len = len > 1 ? (size_t)(len - 1) : 0, .payload = NULL, }; if (msg.len > 0) { msg.payload = malloc(msg.len); if (msg.payload == NULL) { ESP_LOGE(TAG, "failed to allocate command payload"); return false; } memcpy(msg.payload, &payload[1], msg.len); } if (xQueueSend(s_cmd_queue, &msg, pdMS_TO_TICKS(500)) != pdPASS) { free(msg.payload); ESP_LOGW(TAG, "command queue full (cmd 0x%02x)", (unsigned)msg.msg_id); return false; } return true; } esp_err_t host_send_framed(const uint8_t *payload, size_t len) { if (payload == NULL || len == 0 || len > MAX_PAYLOAD_SIZE) { return ESP_ERR_INVALID_ARG; } if (s_tx_fn == NULL) { return ESP_ERR_INVALID_STATE; } uint8_t checksum = 0; for (size_t i = 0; i < len; i++) { checksum ^= payload[i]; } uint8_t frame[4 + MAX_PAYLOAD_SIZE]; size_t pos = 0; frame[pos++] = START_MARKER; frame[pos++] = (uint8_t)len; memcpy(&frame[pos], payload, len); pos += len; frame[pos++] = checksum; frame[pos++] = STOP_MARKER; return s_tx_fn(frame, pos); } void host_rx_bytes(const uint8_t *data, size_t len) { if (data == NULL || len == 0) { return; } TickType_t now = xTaskGetTickCount(); if (s_rx_packet.state != STATE_START && (now - s_last_byte_ticks) > s_rx_timeout_ticks) { s_rx_packet.state = STATE_START; } for (size_t i = 0; i < len; i++) { if (parse_uart_byte(data[i], &s_rx_packet)) { uint8_t cmd = s_rx_packet.len > 0 ? s_rx_packet.payload[0] : 0; /* OTA payloads are high-rate; avoid INFO spam starving the dispatcher. */ if (cmd == (uint8_t)alox_MessageType_OTA_PAYLOAD) { ESP_LOGD(TAG, "received message cmd=0x%02x len=%u", cmd, (unsigned)s_rx_packet.len); } else { ESP_LOGI(TAG, "received message cmd=0x%02x len=%u", cmd, (unsigned)s_rx_packet.len); } host_enqueue_packet(s_rx_packet.payload, s_rx_packet.len); } } s_last_byte_ticks = now; }