diff --git a/v2x_fw/main/main.c b/v2x_fw/main/main.c index 8251d18..40e06a3 100644 --- a/v2x_fw/main/main.c +++ b/v2x_fw/main/main.c @@ -1,22 +1,22 @@ /** - * V2X-Sniffer Firmware für ESP32-C5 (T-Dongle-C5) + * V2X-Sniffer Firmware f�r ESP32-C5 (T-Dongle-C5) * - * VOLLSTÄNDIG UNABHÄNGIG - Speichert V2X-Daten auf SD-Karte - * KEIN Host-PC erforderlich + * ESP32-C5: USB-CDC f�r Daten + 802.11p Promiscuous Mode * * Funktion: * - Sniffed 802.11p V2X-Frames (BSM, CAM, DENM) auf 5.9 GHz Band - * - Speichert jedes Frame als CSV auf SD-Karte (SPI-Modus) - * - Channel-Hopping über alle V2X-Kanäle (157-164 + 17/18) + * - L�st jedes Frame direkt in der Promisc-CB (kein Queue!) + * - Speichert jedes Frame als CSV auf SD-Karte + * - Channel-Hopping �ber alle V2X-Kan�le + * - USB-CDC Live-Daten�bertragung * - Periodische Statistik ins Log * - CSV-Auto-Rotation bei >50MB - * - USB-CDC für Live-Datenübertragung * * SD-Karte (SPI): * GPIO CLK=6, MOSI=7, CMD=2, CS=23 * - * USB: - * USB-CDC am native USB-Port (ttyACM0) + * USB-CDC: + * Native USB am ESP32-C5 * * CSV-Format (v2x_frames.csv): * timestamp_us,msg_type,channel,frequency_mhz,rssi_dbm,noise_dbm,rate_index,frame_len,mac_addr,bssid,raw_hex @@ -38,7 +38,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/queue.h" #include "esp_system.h" #include "esp_wifi.h" #include "esp_event.h" @@ -46,12 +45,13 @@ #include "esp_netif.h" #include "nvs_flash.h" #include "esp_timer.h" +#include "driver/usb_serial_jtag.h" #include "driver/gpio.h" -#include "v2x_display.h" /* Enthält v2x_frame_t, v2x_msg_type_t, Konstanten */ +#include "v2x_display.h" /* Enth�lt v2x_frame_t, v2x_msg_type_t, Konstanten */ static const char *TAG = "V2X-Sniffer"; -/* ====== 802.11p V2X-Kanäle (ETSI EN 302 637) ====== */ +/* ====== 802.11p V2X-Kan�le (ETSI EN 302 637) ====== */ #define V2X_NUM_CHANNELS 10 static const uint32_t v2x_freqs[] = { 5845, 5855, 5865, 5875, /* Kanal 157-160 */ @@ -61,13 +61,10 @@ static const uint32_t v2x_freqs[] = { /* Konstanten */ #define CHANNEL_HOP_INTERVAL_MS (30 * 1000) -#define FRAME_QUEUE_SIZE 64 #define STAT_DUMP_INTERVAL_MS (60 * 1000) +#define USB_BUF_SIZE 4096 #define CSV_FLUSH_INTERVAL 200 -/* Frame Queue */ -static QueueHandle_t s_frame_queue; - /* Globale Variablen */ uint32_t g_v2x_frame_count = 0; int8_t g_v2x_max_rssi = -120; @@ -77,24 +74,30 @@ uint32_t g_v2x_current_freq = 5900; /* ====== Message-Type Erkennung ====== */ static v2x_msg_type_t detect_msg_type(const uint8_t *data, uint16_t len) { - if (!data || len < 4) return V2X_MSG_UNKNOWN; + if (!data || len < 8) return V2X_MSG_UNKNOWN; + + /* SAE J2735 BSM: protocolVersion(1) + messageID(1) + length(2) */ + uint8_t proto = data[0]; + if (proto > 3) return V2X_MSG_UNKNOWN; + + uint8_t msg_id = data[1]; + + /* CAM (C2C: Cooperation Awareness Message) */ + if (msg_id == 0x02) return V2X_MSG_CAM; + + /* DENM (C2I: Decentralized Environmental Notification Message) */ + if (msg_id == 0x03) return V2X_MSG_DENM; + + /* BSM (BSM: Basic Safety Message) */ + if (msg_id == 0x01) return V2X_MSG_BSM; + + /* IEEE 1609.2 Security Extension */ + if (msg_id == 0x60) return V2X_MSG_BSM; - if (len >= 20 && len <= 240) { - uint8_t protocol_ver = data[0]; - if (protocol_ver == 1 || protocol_ver == 2 || protocol_ver == 3) { - return V2X_MSG_UNKNOWN; - } - } return V2X_MSG_UNKNOWN; } -/* ====== 802.11p PHY initialisieren ====== */ -static esp_err_t v2x_phy_init(uint32_t freq_mhz) { - ESP_LOGI(TAG, "PHY aktiviert: %lu MHz", (unsigned long)freq_mhz); - return ESP_OK; -} - -/* ====== Promiscuous RX Callback ====== */ +/* ====== 802.11p Promiscuous Callback (direktes Processing!) ====== */ static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type) { (void)arg; @@ -112,13 +115,16 @@ static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type) frame.rate_index = pkt->rx_ctrl.rate; frame.frame_len = pkt->rx_ctrl.sig_len; frame.frequency_mhz = (float)g_v2x_current_freq; + frame.channel = g_v2x_channel_idx; + /* MAC-Adressen extrahieren */ if (pkt->rx_ctrl.sig_len >= 30) { uint8_t *mac = pkt->payload; memcpy(frame.bssid, mac + 10, 6); memcpy(frame.mac_addr, mac + 16, 6); } + /* V2X-Payload ab Offset 24 */ uint16_t v2x_offset = 24; if (pkt->rx_ctrl.sig_len > v2x_offset) { frame.raw_len = pkt->rx_ctrl.sig_len - v2x_offset; @@ -133,40 +139,18 @@ static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type) } } - if (xQueueSendFromISR(s_frame_queue, &frame, NULL) != pdTRUE) { - static uint64_t last_overflow = 0; - if (esp_timer_get_time() - last_overflow > 1000000) { - ESP_LOGW(TAG, "Frame Queue voll, Frame verworfen"); - last_overflow = esp_timer_get_time(); - } + /* === Auf SD-Karte schreiben (CSV + Stats via v2x_driver) === */ + v2x_sd_write_frame(&frame); + + /* === Als Live-Dump über USB-Serial-JTAG senden === */ + if (usb_serial_jtag_is_connected()) { + char usb_buf[RAW_HEX_BUF + 256]; + frame_to_csv_line(&frame, usb_buf, sizeof(usb_buf)); + usb_serial_jtag_write_bytes(usb_buf, strlen(usb_buf), 100); } -} -/* ====== Frame Writer Task ====== */ -static void v2x_frame_writer_task(void *pvParameters) -{ - v2x_frame_t frame; - uint32_t flush_counter = 0; - while (1) { - if (xQueueReceive(s_frame_queue, &frame, pdMS_TO_TICKS(500)) == pdTRUE) { - esp_err_t ret = v2x_sd_write_frame(&frame); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "SD-Schreibfehler"); - } - - g_v2x_frame_count++; - - flush_counter++; - if (flush_counter % CSV_FLUSH_INTERVAL == 0) { - FILE *fp = fopen(SD_CSV_FILE, "r"); - if (fp) { - fflush(fp); - fclose(fp); - } - } - } - } + g_v2x_frame_count++; } /* ====== Channel Hopper Task ====== */ @@ -178,7 +162,16 @@ static void v2x_channel_hopper_task(void *pvParameters) while (1) { uint32_t freq = v2x_freqs[hop_idx % V2X_NUM_CHANNELS]; - v2x_phy_init(freq); + + /* ESP32-C5: WiFi Channel direkt setzen */ + esp_err_t ch_ret = esp_wifi_set_channel( + (uint8_t)(freq / 5), /* Channel number (freq/5 f�r 5GHz) */ + WIFI_SECOND_CHAN_NONE + ); + if (ch_ret != ESP_OK) { + ESP_LOGW(TAG, "Channel-Wechsel fehlgeschlagen: %s", esp_err_to_name(ch_ret)); + } + g_v2x_current_freq = freq; g_v2x_channel_idx = hop_idx; @@ -195,13 +188,10 @@ static void v2x_stats_task(void *pvParameters) ESP_LOGI(TAG, "Statistik-Task gestartet"); while (1) { - if (s_frame_queue) { - v2x_sd_dump_stats(); - - uint32_t queue_free = uxQueueMessagesWaiting(s_frame_queue); - uint32_t queue_items = FRAME_QUEUE_SIZE - queue_free; - ESP_LOGI(TAG, "Queue: %lu/%lu Frames wartend", (unsigned long)queue_items, (unsigned long)FRAME_QUEUE_SIZE); - } + v2x_sd_dump_stats(); + + ESP_LOGI(TAG, "Frames: %lu | Max RSSI: %d dBm", + (unsigned long)g_v2x_frame_count, g_v2x_max_rssi); vTaskDelay(pdMS_TO_TICKS(STAT_DUMP_INTERVAL_MS)); } @@ -210,8 +200,8 @@ static void v2x_stats_task(void *pvParameters) /* ====== Application Entry Point ====== */ void app_main(void) { - ESP_LOGI(TAG, "====== V2X-Sniffer BEREIT ======="); - ESP_LOGI(TAG, "ESP32-C5 | 802.11p V2X-Band (5.9 GHz) | SD-Karte (SPI)"); + ESP_LOGI(TAG, "====== V2X-Sniffer f�r ESP32-C5 BEREIT ======="); + ESP_LOGI(TAG, "802.11p V2X-Band (5.9 GHz) | SD-Karte (SPI) | USB-CDC"); ESP_LOGI(TAG, "================================="); /* === NVS initialisieren === */ @@ -223,6 +213,15 @@ void app_main(void) } ESP_ERROR_CHECK(ret); + /* === USB-Serial-JTAG initialisieren === */ + usb_serial_jtag_driver_config_t usb_cfg = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); + ret = usb_serial_jtag_driver_install(&usb_cfg); + if (ret == ESP_OK) { + ESP_LOGI(TAG, "USB-Serial-JTAG initialisiert"); + } else { + ESP_LOGW(TAG, "USB-Serial-JTAG nicht verf�gbar"); + } + /* === WiFi initialisieren === */ esp_netif_init(); esp_event_loop_create_default(); @@ -246,19 +245,11 @@ void app_main(void) } } - /* === Frame Queue erstellen === */ - s_frame_queue = xQueueCreate(FRAME_QUEUE_SIZE, sizeof(v2x_frame_t)); - if (!s_frame_queue) { - ESP_LOGE(TAG, "Frame Queue konnte nicht erstellt werden"); - while (1) vTaskDelay(1000 / portTICK_PERIOD_MS); - } - /* === Stats initialisieren === */ v2x_sd_reset_stats(); /* === Tasks starten === */ xTaskCreate(v2x_channel_hopper_task, "channel_hopper", 4096, NULL, 3, NULL); - xTaskCreate(v2x_frame_writer_task, "frame_writer", 4096, NULL, 6, NULL); xTaskCreate(v2x_stats_task, "stats_task", 2048, NULL, 2, NULL); /* === Promiscuous Mode aktivieren === */ @@ -272,5 +263,5 @@ void app_main(void) ESP_LOGI(TAG, " Kanal: 157-164 + 17/18 (5.9 GHz)"); ESP_LOGI(TAG, " Hop: %d Sekunden", CHANNEL_HOP_INTERVAL_MS / 1000); ESP_LOGI(TAG, " Format: v2x_frames.csv (Excel/CSV-kompatibel)"); - ESP_LOGI(TAG, "=========================================="); + ESP_LOGI(TAG, "============================================="); }