瀏覽代碼

Update from fw repo

Willy-JL 2 年之前
父節點
當前提交
fa3ffeff61

+ 16 - 12
evil_portal/evil_portal_app.c

@@ -25,12 +25,12 @@ static void evil_portal_app_tick_event_callback(void* context) {
 Evil_PortalApp* evil_portal_app_alloc() {
     Evil_PortalApp* app = malloc(sizeof(Evil_PortalApp));
 
-    app->sent_html = false;
-    app->sent_ap = false;
     app->sent_reset = false;
-    app->has_command_queue = false;
-    app->command_index = 0;
     app->portal_logs = furi_string_alloc();
+    app->portal_logs_mutex = furi_mutex_alloc(FuriMutexTypeRecursive);
+
+    app->capture_line = false;
+    app->captured_line = furi_string_alloc();
 
     app->dialogs = furi_record_open(RECORD_DIALOGS);
     app->file_path = furi_string_alloc();
@@ -82,15 +82,8 @@ Evil_PortalApp* evil_portal_app_alloc() {
 }
 
 void evil_portal_app_free(Evil_PortalApp* app) {
-    // save latest logs
-    if(furi_string_utf8_length(app->portal_logs) > 0) {
-        write_logs(app->portal_logs);
-        furi_string_free(app->portal_logs);
-    }
-
     // Send reset event to dev board
-    evil_portal_uart_tx((uint8_t*)(RESET_CMD), strlen(RESET_CMD));
-    evil_portal_uart_tx((uint8_t*)("\n"), 1);
+    evil_portal_uart_tx((uint8_t*)(RESET_CMD "\nstopscan\n"), strlen(RESET_CMD "\nstopscan\n"));
 
     furi_assert(app);
 
@@ -111,6 +104,17 @@ void evil_portal_app_free(Evil_PortalApp* app) {
 
     evil_portal_uart_free(app->uart);
 
+    // save latest logs
+    furi_mutex_acquire(app->portal_logs_mutex, FuriWaitForever);
+    if(furi_string_size(app->portal_logs) > 0) {
+        write_logs(app->portal_logs);
+        furi_string_free(app->portal_logs);
+    }
+    furi_mutex_release(app->portal_logs_mutex);
+    furi_mutex_free(app->portal_logs_mutex);
+
+    furi_string_free(app->captured_line);
+
     // Close records
     furi_record_close(RECORD_GUI);
 

+ 4 - 5
evil_portal/evil_portal_app_i.h

@@ -34,9 +34,7 @@ struct Evil_PortalApp {
     SceneManager* scene_manager;
 
     FuriString* portal_logs;
-    const char* command_queue[1];
-    int command_index;
-    bool has_command_queue;
+    FuriMutex* portal_logs_mutex;
 
     FuriString* text_box_store;
     size_t text_box_store_strlen;
@@ -57,12 +55,13 @@ struct Evil_PortalApp {
     bool is_custom_tx_string;
     bool focus_console_start;
     bool show_stopscan_tip;
-    bool sent_ap;
-    bool sent_html;
     bool sent_reset;
     int BAUDRATE;
     char text_store[2][128 + 1];
 
+    bool capture_line;
+    FuriString* captured_line;
+
     uint8_t* index_html;
     uint8_t* ap_name;
 };

+ 6 - 31
evil_portal/evil_portal_uart.c

@@ -48,52 +48,28 @@ static int32_t uart_worker(void* context) {
                 if(uart->handle_rx_data_cb) {
                     uart->handle_rx_data_cb(uart->rx_buf, len, uart->app);
 
-                    if(uart->app->has_command_queue) {
-                        if(uart->app->command_index < 1) {
-                            if(0 == strncmp(
-                                        SET_AP_CMD,
-                                        uart->app->command_queue[uart->app->command_index],
-                                        strlen(SET_AP_CMD))) {
-                                FuriString* out_data = furi_string_alloc();
-
-                                furi_string_cat(out_data, "setap=");
-                                furi_string_cat(out_data, (char*)uart->app->ap_name);
-
-                                evil_portal_uart_tx(
-                                    (uint8_t*)(furi_string_get_cstr(out_data)),
-                                    strlen(furi_string_get_cstr(out_data)));
-                                evil_portal_uart_tx((uint8_t*)("\n"), 1);
-
-                                uart->app->sent_ap = true;
-
-                                free(out_data);
-                                free(uart->app->ap_name);
-                            }
-
-                            uart->app->command_index = 0;
-                            uart->app->has_command_queue = false;
-                            uart->app->command_queue[0] = "";
-                        }
-                    }
-
+                    furi_mutex_acquire(uart->app->portal_logs_mutex, FuriWaitForever);
                     if(uart->app->sent_reset == false) {
                         furi_string_cat(uart->app->portal_logs, (char*)uart->rx_buf);
                     }
 
-                    if(furi_string_utf8_length(uart->app->portal_logs) > 4000) {
+                    if(furi_string_size(uart->app->portal_logs) > 4000) {
                         write_logs(uart->app->portal_logs);
                         furi_string_reset(uart->app->portal_logs);
                     }
+                    furi_mutex_release(uart->app->portal_logs_mutex);
                 } else {
                     uart->rx_buf[len] = '\0';
+                    furi_mutex_acquire(uart->app->portal_logs_mutex, FuriWaitForever);
                     if(uart->app->sent_reset == false) {
                         furi_string_cat(uart->app->portal_logs, (char*)uart->rx_buf);
                     }
 
-                    if(furi_string_utf8_length(uart->app->portal_logs) > 4000) {
+                    if(furi_string_size(uart->app->portal_logs) > 4000) {
                         write_logs(uart->app->portal_logs);
                         furi_string_reset(uart->app->portal_logs);
                     }
+                    furi_mutex_release(uart->app->portal_logs_mutex);
                 }
             }
         }
@@ -128,7 +104,6 @@ Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app) {
         furi_hal_uart_init(UART_CH, app->BAUDRATE);
     }
 
-    furi_hal_console_disable();
     if(app->BAUDRATE == 0) {
         app->BAUDRATE = 115200;
     }

+ 4 - 3
evil_portal/helpers/evil_portal_storage.c

@@ -83,7 +83,7 @@ void evil_portal_read_ap_name(void* context) {
     if(storage_common_stat(storage, EVIL_PORTAL_AP_SAVE_PATH, &fi) == FSE_OK) {
         File* ap_name = storage_file_alloc(storage);
         if(storage_file_open(ap_name, EVIL_PORTAL_AP_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
-            app->ap_name = malloc((size_t)fi.size);
+            app->ap_name = malloc((size_t)fi.size + 1);
             uint8_t* buf_ptr = app->ap_name;
             size_t read = 0;
             while(read < fi.size) {
@@ -93,6 +93,8 @@ void evil_portal_read_ap_name(void* context) {
                 read += now_read;
                 buf_ptr += now_read;
             }
+            *buf_ptr = '\0';
+            buf_ptr++;
             free(buf_ptr);
         }
         storage_file_close(ap_name);
@@ -154,8 +156,7 @@ void write_logs(FuriString* portal_logs) {
     File* file = storage_file_alloc(storage);
 
     if(storage_file_open(file, seq_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
-        storage_file_write(
-            file, furi_string_get_cstr(portal_logs), furi_string_utf8_length(portal_logs));
+        storage_file_write(file, furi_string_get_cstr(portal_logs), furi_string_size(portal_logs));
     }
     storage_file_close(file);
     storage_file_free(file);

+ 69 - 24
evil_portal/scenes/evil_portal_scene_console_output.c

@@ -1,5 +1,6 @@
 #include "../evil_portal_app_i.h"
 #include "../helpers/evil_portal_storage.h"
+#include <m-string.h>
 
 void evil_portal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
     furi_assert(context);
@@ -16,7 +17,15 @@ void evil_portal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void
     buf[len] = '\0';
     furi_string_cat_printf(app->text_box_store, "%s", buf);
 
-    view_dispatcher_send_custom_event(app->view_dispatcher, Evil_PortalEventRefreshConsoleOutput);
+    if(app->capture_line) {
+        furi_string_cat_printf(app->captured_line, "%s", buf);
+    }
+
+    text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
+}
+
+static inline bool captured(Evil_PortalApp* app, const char* str) {
+    return furi_string_search_str(app->captured_line, str) != STRING_FAILURE;
 }
 
 void evil_portal_scene_console_output_on_enter(void* context) {
@@ -53,8 +62,10 @@ void evil_portal_scene_console_output_on_enter(void* context) {
             const char* help_msg = "Logs saved.\n\n";
             furi_string_cat_str(app->text_box_store, help_msg);
             app->text_box_store_strlen += strlen(help_msg);
+            furi_mutex_acquire(app->portal_logs_mutex, FuriWaitForever);
             write_logs(app->portal_logs);
             furi_string_reset(app->portal_logs);
+            furi_mutex_release(app->portal_logs_mutex);
             if(app->show_stopscan_tip) {
                 const char* msg = "Press BACK to return\n";
                 furi_string_cat_str(app->text_box_store, msg);
@@ -73,11 +84,9 @@ void evil_portal_scene_console_output_on_enter(void* context) {
         }
 
         if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
-            app->command_queue[0] = SET_AP_CMD;
-            app->has_command_queue = true;
-            app->command_index = 0;
             if(app->show_stopscan_tip) {
-                const char* msg = "Starting portal\nIf no response press\nBACK to return\n";
+                const char* msg =
+                    "Starting portal\nMarauder takes a few secs to start\nPress BACK to return\n";
                 furi_string_cat_str(app->text_box_store, msg);
                 app->text_box_store_strlen += strlen(msg);
             }
@@ -104,28 +113,67 @@ void evil_portal_scene_console_output_on_enter(void* context) {
 
     if(app->is_command && app->selected_tx_string) {
         if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
-            evil_portal_read_index_html(context);
-
             FuriString* data = furi_string_alloc();
-            furi_string_cat(data, "sethtml=");
-            furi_string_cat(data, (char*)app->index_html);
+            app->capture_line = true;
 
-            evil_portal_uart_tx(
-                (uint8_t*)(furi_string_get_cstr(data)), strlen(furi_string_get_cstr(data)));
-            evil_portal_uart_tx((uint8_t*)("\n"), 1);
+            evil_portal_read_ap_name(context);
+            // Test evil portal syntax and response, marauder ignores it
+            furi_string_printf(data, "setap=%s\n", (char*)app->ap_name);
+            furi_string_reset(app->captured_line);
+            evil_portal_uart_tx((uint8_t*)(furi_string_get_cstr(data)), furi_string_size(data));
+            // TODO: move timeouts and commands elsewhere, can't block input cycle
+            for(uint8_t t = 0; t < 69 && !captured(app, "ap set") && !captured(app, "\n>"); t++)
+                furi_delay_ms(100);
+            bool icanhazmarauder = !captured(app, "ap set") && // Evil portal didn't respond
+                                   captured(app, "\n>"); // Marauder did respond
+            // Not evil portal, set up marauder
+            if(icanhazmarauder) {
+                furi_string_printf(data, "clearlist -a -s -c\nssid -a -n '%s'\n", app->ap_name);
+                furi_string_reset(app->captured_line);
+                evil_portal_uart_tx(
+                    (uint8_t*)(furi_string_get_cstr(data)), furi_string_size(data));
+                // Marauder echoes the command, maybe still init so wait a while for echo
+                for(uint8_t t = 0; t < 10 && !captured(app, (char*)app->ap_name); t++)
+                    furi_delay_ms(100);
+            }
+            free(app->ap_name);
 
-            app->sent_html = true;
+            evil_portal_read_index_html(context);
+            if(icanhazmarauder) {
+                furi_string_reset(app->captured_line);
+                evil_portal_uart_tx(
+                    (uint8_t*)("evilportal -c sethtmlstr\n"),
+                    strlen("evilportal -c sethtmlstr\n"));
+                for(uint8_t t = 0; t < 10 && !captured(app, "\n>") &&
+                                   !captured(app, "Setting HTML from serial...");
+                    t++)
+                    furi_delay_ms(100);
+                // Check for active attack
+                if(!(captured(app, "\n>") && !captured(app, "Setting HTML from serial..."))) {
+                    furi_string_reset(app->captured_line);
+                    evil_portal_uart_tx(app->index_html, strlen((char*)app->index_html));
+                    evil_portal_uart_tx((uint8_t*)("\n"), 1);
+                    for(uint8_t t = 0; t < 20 && !captured(app, "html set"); t++)
+                        furi_delay_ms(100);
+                    evil_portal_uart_tx(
+                        (uint8_t*)("evilportal -c start\n"), strlen("evilportal -c start\n"));
+                }
+            } else {
+                furi_string_set(data, "sethtml=");
+                furi_string_cat(data, (char*)app->index_html);
+                evil_portal_uart_tx(
+                    (uint8_t*)(furi_string_get_cstr(data)), strlen(furi_string_get_cstr(data)));
+                evil_portal_uart_tx((uint8_t*)("\n"), 1);
+            }
 
-            free(data);
             free(app->index_html);
-
-            evil_portal_read_ap_name(context);
+            app->capture_line = false;
+            furi_string_reset(app->captured_line);
+            furi_string_free(data);
         } else if(0 == strncmp(RESET_CMD, app->selected_tx_string, strlen(RESET_CMD))) {
-            app->sent_html = false;
-            app->sent_ap = false;
             evil_portal_uart_tx(
                 (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-            evil_portal_uart_tx((uint8_t*)("\n"), 1);
+            evil_portal_uart_tx((uint8_t*)("\nstopscan\n"), strlen("\nstopscan\n"));
         } else if(1 == strncmp("help", app->selected_tx_string, strlen("help"))) {
             evil_portal_uart_tx(
                 (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
@@ -135,14 +183,11 @@ void evil_portal_scene_console_output_on_enter(void* context) {
 }
 
 bool evil_portal_scene_console_output_on_event(void* context, SceneManagerEvent event) {
-    Evil_PortalApp* app = context;
+    UNUSED(context);
 
     bool consumed = false;
 
-    if(event.type == SceneManagerEventTypeCustom) {
-        text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
-        consumed = true;
-    } else if(event.type == SceneManagerEventTypeTick) {
+    if(event.type == SceneManagerEventTypeTick) {
         consumed = true;
     }
 

+ 84 - 19
gps_nmea/gps.c

@@ -20,7 +20,53 @@ static void render_callback(Canvas* const canvas, void* context) {
     GpsUart* gps_uart = context;
     furi_mutex_acquire(gps_uart->mutex, FuriWaitForever);
 
-    if(!gps_uart->changing_baudrate) {
+    char buffer[64];
+
+    switch(gps_uart->view_state) {
+    case CHANGE_BAUDRATE:
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignBottom, "Baudrate set to:");
+        snprintf(buffer, 64, "%ld baud", gps_uart->baudrate);
+        canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, buffer);
+        break;
+    case CHANGE_BACKLIGHT:
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str_aligned(
+            canvas,
+            64,
+            32,
+            AlignCenter,
+            AlignBottom,
+            gps_uart->backlight_enabled ? "Backlight enabled" : "Backlight disabled");
+        break;
+    case CHANGE_DEEPSLEEP:
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str_aligned(
+            canvas,
+            64,
+            32,
+            AlignCenter,
+            AlignBottom,
+            gps_uart->deep_sleep_enabled ? "Deep sleep enabled" : "Deep sleep disabled");
+        break;
+    case CHANGE_SPEEDUNIT:
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignBottom, "Speed unit set to:");
+        switch(gps_uart->speed_units) {
+        case KPH:
+            canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, "km/h");
+            break;
+        case MPH:
+            canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, "mi/h");
+            break;
+        case KNOTS:
+        default:
+            canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, "kn");
+            break;
+        }
+        break;
+    case NORMAL:
+    default:
         canvas_set_font(canvas, FontPrimary);
         canvas_draw_str_aligned(canvas, 32, 8, AlignCenter, AlignBottom, "Latitude");
         canvas_draw_str_aligned(canvas, 96, 8, AlignCenter, AlignBottom, "Longitude");
@@ -31,7 +77,6 @@ static void render_callback(Canvas* const canvas, void* context) {
         canvas_draw_str_aligned(canvas, 96, 52, AlignCenter, AlignBottom, "Last Fix");
 
         canvas_set_font(canvas, FontSecondary);
-        char buffer[64];
         snprintf(buffer, 64, "%f", (double)gps_uart->status.latitude);
         canvas_draw_str_aligned(canvas, 32, 18, AlignCenter, AlignBottom, buffer);
         snprintf(buffer, 64, "%f", (double)gps_uart->status.longitude);
@@ -41,10 +86,10 @@ static void render_callback(Canvas* const canvas, void* context) {
 
         switch(gps_uart->speed_units) {
         case KPH:
-            snprintf(buffer, 64, "%.2f km", (double)(gps_uart->status.speed * KNOTS_TO_KPH));
+            snprintf(buffer, 64, "%.2f km/h", (double)(gps_uart->status.speed * KNOTS_TO_KPH));
             break;
         case MPH:
-            snprintf(buffer, 64, "%.2f mi", (double)(gps_uart->status.speed * KNOTS_TO_MPH));
+            snprintf(buffer, 64, "%.2f mi/h", (double)(gps_uart->status.speed * KNOTS_TO_MPH));
             break;
         case KNOTS:
         default:
@@ -70,13 +115,7 @@ static void render_callback(Canvas* const canvas, void* context) {
             gps_uart->status.time_minutes,
             gps_uart->status.time_seconds);
         canvas_draw_str_aligned(canvas, 96, 62, AlignCenter, AlignBottom, buffer);
-    } else {
-        char buffer[64];
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignBottom, "Baudrate set to:");
-
-        snprintf(buffer, 64, "%ld baud", gps_uart->baudrate);
-        canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, buffer);
+        break;
     }
 
     furi_mutex_release(gps_uart->mutex);
@@ -135,17 +174,23 @@ int32_t gps_app(void* p) {
                         processing = false;
                         break;
                     case InputKeyOk:
-                        if(!gps_uart->backlight_on) {
+                        if(!gps_uart->backlight_enabled) {
                             notification_message_block(
                                 gps_uart->notifications, &sequence_display_backlight_enforce_on);
-                            gps_uart->backlight_on = true;
+                            gps_uart->backlight_enabled = true;
                         } else {
                             notification_message_block(
                                 gps_uart->notifications, &sequence_display_backlight_enforce_auto);
                             notification_message(
                                 gps_uart->notifications, &sequence_display_backlight_off);
-                            gps_uart->backlight_on = false;
+                            gps_uart->backlight_enabled = false;
                         }
+
+                        gps_uart->view_state = CHANGE_BACKLIGHT;
+                        furi_mutex_release(gps_uart->mutex);
+                        view_port_update(view_port);
+                        furi_delay_ms(1000);
+                        gps_uart->view_state = NORMAL;
                         break;
                     default:
                         break;
@@ -163,15 +208,37 @@ int32_t gps_app(void* p) {
                         gps_uart->baudrate = gps_baudrates[current_gps_baudrate];
 
                         gps_uart_init_thread(gps_uart);
-                        gps_uart->changing_baudrate = true;
+                        gps_uart->view_state = CHANGE_BAUDRATE;
+
                         furi_mutex_release(gps_uart->mutex);
                         view_port_update(view_port);
+                        furi_delay_ms(1000);
+                        gps_uart->view_state = NORMAL;
                         break;
                     case InputKeyRight:
                         gps_uart->speed_units++;
                         if(gps_uart->speed_units == INVALID) {
                             gps_uart->speed_units = KNOTS;
                         }
+
+                        gps_uart->view_state = CHANGE_SPEEDUNIT;
+                        furi_mutex_release(gps_uart->mutex);
+                        view_port_update(view_port);
+                        furi_delay_ms(1000);
+                        gps_uart->view_state = NORMAL;
+                        break;
+                    case InputKeyDown:
+                        gps_uart->view_state = CHANGE_DEEPSLEEP;
+                        gps_uart->deep_sleep_enabled = !gps_uart->deep_sleep_enabled;
+
+                        // tested on Telit SE868-A and SL871L-S
+                        furi_hal_uart_tx(
+                            UART_CH, (uint8_t*)"$PMTK161,0*28\r\n", strlen("$PMTK161,0*28\r\n"));
+
+                        furi_mutex_release(gps_uart->mutex);
+                        view_port_update(view_port);
+                        furi_delay_ms(1000);
+                        gps_uart->view_state = NORMAL;
                         break;
                     case InputKeyBack:
                         processing = false;
@@ -182,12 +249,10 @@ int32_t gps_app(void* p) {
                 }
             }
         }
-        if(!gps_uart->changing_baudrate) {
+
+        if(gps_uart->view_state == NORMAL) {
             furi_mutex_release(gps_uart->mutex);
             view_port_update(view_port);
-        } else {
-            furi_delay_ms(1000);
-            gps_uart->changing_baudrate = false;
         }
     }
 

+ 5 - 2
gps_nmea/gps_uart.c

@@ -28,6 +28,8 @@ static void gps_uart_serial_init(GpsUart* gps_uart) {
 
     furi_hal_uart_set_irq_cb(UART_CH, gps_uart_on_irq_cb, gps_uart);
     furi_hal_uart_set_br(UART_CH, gps_uart->baudrate);
+
+    furi_hal_uart_tx(UART_CH, (uint8_t*)"wakey wakey\r\n", strlen("wakey wakey\r\n"));
 }
 
 static void gps_uart_serial_deinit(GpsUart* gps_uart) {
@@ -211,9 +213,10 @@ GpsUart* gps_uart_enable() {
     gps_uart->notifications = furi_record_open(RECORD_NOTIFICATION);
 
     gps_uart->baudrate = gps_baudrates[current_gps_baudrate];
-    gps_uart->changing_baudrate = false;
-    gps_uart->backlight_on = false;
     gps_uart->speed_units = KNOTS;
+    gps_uart->backlight_enabled = false;
+    gps_uart->deep_sleep_enabled = false;
+    gps_uart->view_state = NORMAL;
 
     gps_uart_init_thread(gps_uart);
 

+ 11 - 2
gps_nmea/gps_uart.h

@@ -30,6 +30,14 @@ typedef struct {
 
 typedef enum { KNOTS, KPH, MPH, INVALID } SpeedUnit;
 
+typedef enum {
+    CHANGE_BAUDRATE,
+    CHANGE_BACKLIGHT,
+    CHANGE_DEEPSLEEP,
+    CHANGE_SPEEDUNIT,
+    NORMAL
+} ViewState;
+
 typedef struct {
     FuriMutex* mutex;
     FuriThread* thread;
@@ -38,9 +46,10 @@ typedef struct {
 
     NotificationApp* notifications;
     uint32_t baudrate;
-    bool changing_baudrate;
-    bool backlight_on;
+    bool backlight_enabled;
+    bool deep_sleep_enabled;
     SpeedUnit speed_units;
+    ViewState view_state;
 
     GpsStatus status;
 } GpsUart;

+ 0 - 1
mifare_fuzzer/mifare_fuzzer_i.h

@@ -68,7 +68,6 @@ struct MifareFuzzerApp {
 
     MifareCard card;
     MifareFuzzerAttack attack;
-    FuriHalNfcDevData nfc_dev_data;
     FuriString* app_folder;
     FuriString* file_path;
     FuriString* uid_str;

+ 34 - 13
mifare_fuzzer/mifare_fuzzer_worker.c

@@ -1,4 +1,3 @@
-
 #include "mifare_fuzzer_worker.h"
 
 /// @brief mifare_fuzzer_worker_alloc()
@@ -9,6 +8,10 @@ MifareFuzzerWorker* mifare_fuzzer_worker_alloc() {
     mifare_fuzzer_worker->thread = furi_thread_alloc_ex(
         "MifareFuzzerWorker", 8192, mifare_fuzzer_worker_task, mifare_fuzzer_worker);
     mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop;
+
+    mifare_fuzzer_worker->nfc = nfc_alloc();
+    mifare_fuzzer_worker->nfc_device = nfc_device_alloc();
+
     return mifare_fuzzer_worker;
 }
 
@@ -17,6 +20,10 @@ MifareFuzzerWorker* mifare_fuzzer_worker_alloc() {
 void mifare_fuzzer_worker_free(MifareFuzzerWorker* mifare_fuzzer_worker) {
     furi_assert(mifare_fuzzer_worker);
     furi_thread_free(mifare_fuzzer_worker->thread);
+
+    nfc_free(mifare_fuzzer_worker->nfc);
+    nfc_device_free(mifare_fuzzer_worker->nfc_device);
+
     free(mifare_fuzzer_worker);
 }
 
@@ -45,14 +52,19 @@ int32_t mifare_fuzzer_worker_task(void* context) {
     MifareFuzzerWorker* mifare_fuzzer_worker = context;
 
     if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
-        FuriHalNfcDevData params = mifare_fuzzer_worker->nfc_dev_data;
+        const Iso14443_3aData* data =
+            nfc_device_get_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a);
+
+        mifare_fuzzer_worker->nfc_listener =
+            nfc_listener_alloc(mifare_fuzzer_worker->nfc, NfcProtocolIso14443_3a, data);
+        nfc_listener_start(mifare_fuzzer_worker->nfc_listener, NULL, NULL);
 
-        furi_hal_nfc_exit_sleep();
         while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
-            furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 500);
             furi_delay_ms(50);
         }
-        furi_hal_nfc_sleep();
+
+        nfc_listener_stop(mifare_fuzzer_worker->nfc_listener);
+        nfc_listener_free(mifare_fuzzer_worker->nfc_listener);
     }
 
     mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop;
@@ -70,18 +82,27 @@ bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker)
     return false;
 }
 
-/// @brief mifare_fuzzer_worker_set_nfc_dev_data()
+/// @brief mifare_fuzzer_worker_set_nfc_data()
 /// @param mifare_fuzzer_worker
-/// @param nfc_dev_data
-void mifare_fuzzer_worker_set_nfc_dev_data(
+/// @param nfc_data
+void mifare_fuzzer_worker_set_nfc_data(
     MifareFuzzerWorker* mifare_fuzzer_worker,
-    FuriHalNfcDevData nfc_dev_data) {
-    mifare_fuzzer_worker->nfc_dev_data = nfc_dev_data;
+    Iso14443_3aData nfc_data) {
+    Iso14443_3aData* nfc_14a_data = iso14443_3a_alloc();
+    nfc_14a_data->uid_len = nfc_data.uid_len;
+    memcpy(nfc_14a_data->uid, nfc_data.uid, nfc_data.uid_len);
+    memcpy(nfc_14a_data->atqa, nfc_data.atqa, ATQA_LEN);
+    nfc_14a_data->sak = nfc_data.sak;
+
+    nfc_device_clear(mifare_fuzzer_worker->nfc_device);
+    nfc_device_set_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a, nfc_14a_data);
+
+    iso14443_3a_free(nfc_14a_data);
 }
 
-/// @brief mifare_fuzzer_worker_get_nfc_dev_data()
+/// @brief mifare_fuzzer_worker_get_nfc_data()
 /// @param mifare_fuzzer_worker
 /// @return
-FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker) {
-    return mifare_fuzzer_worker->nfc_dev_data;
+Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker) {
+    return mifare_fuzzer_worker->nfc_data;
 }

+ 11 - 4
mifare_fuzzer/mifare_fuzzer_worker.h

@@ -2,6 +2,10 @@
 #include <furi.h>
 #include <furi_hal.h>
 
+#include <nfc/nfc_device.h>
+#include <nfc/nfc_listener.h>
+#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
+
 typedef enum MifareFuzzerWorkerState {
     MifareFuzzerWorkerStateEmulate,
     MifareFuzzerWorkerStateStop,
@@ -13,7 +17,10 @@ typedef enum MifareFuzzerWorkerState {
 typedef struct MifareFuzzerWorker {
     FuriThread* thread;
     MifareFuzzerWorkerState state;
-    FuriHalNfcDevData nfc_dev_data;
+    Iso14443_3aData nfc_data;
+    NfcListener* nfc_listener;
+    NfcDevice* nfc_device;
+    Nfc* nfc;
 } MifareFuzzerWorker;
 
 // worker
@@ -25,7 +32,7 @@ void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker);
 int32_t mifare_fuzzer_worker_task(void* context);
 //
 bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker);
-void mifare_fuzzer_worker_set_nfc_dev_data(
+void mifare_fuzzer_worker_set_nfc_data(
     MifareFuzzerWorker* mifare_fuzzer_worker,
-    FuriHalNfcDevData nfc_dev_data);
-FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker);
+    Iso14443_3aData nfc_data);
+Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker);

+ 36 - 34
mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c

@@ -41,19 +41,21 @@ void mifare_fuzzer_scene_emulator_on_enter(void* context) {
     mifare_fuzzer_emulator_set_ticks_between_cards(
         app->emulator_view, emulator->ticks_between_cards);
     // init default card data
-    FuriHalNfcDevData nfc_dev_data;
-    nfc_dev_data.atqa[0] = 0x00;
-    nfc_dev_data.atqa[1] = 0x00;
-    nfc_dev_data.sak = 0x00;
+    Iso14443_3aData nfc_data;
+    nfc_data.atqa[0] = 0x00;
+    nfc_data.atqa[1] = 0x00;
+    nfc_data.sak = 0x00;
     if(app->card == MifareCardUltralight) {
-        nfc_dev_data.uid_len = 0x07;
+        nfc_data.uid_len = 0x07;
     } else {
-        nfc_dev_data.uid_len = 0x04;
+        nfc_data.uid_len = 0x04;
     }
-    for(uint32_t i = 0; i < nfc_dev_data.uid_len; i++) {
-        nfc_dev_data.uid[i] = 0x00;
+    for(uint32_t i = 0; i < nfc_data.uid_len; i++) {
+        nfc_data.uid[i] = 0x00;
     }
-    mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data);
+
+    mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, nfc_data);
+
     // init other vars
     attack_step = 0;
 
@@ -67,7 +69,7 @@ void mifare_fuzzer_scene_emulator_on_enter(void* context) {
 /// @return
 bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent event) {
     //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event()");
-    FuriHalNfcDevData nfc_dev_data;
+    Iso14443_3aData nfc_data;
 
     MifareFuzzerApp* app = context;
     MifareFuzzerEmulator* emulator = app->emulator_view;
@@ -84,27 +86,27 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
             // Set card type
             // TODO: Move somewhere else, I do not like this to be there
             if(app->card == MifareCardClassic1k) {
-                nfc_dev_data.atqa[0] = 0x04;
-                nfc_dev_data.atqa[1] = 0x00;
-                nfc_dev_data.sak = 0x08;
-                nfc_dev_data.uid_len = 0x04;
+                nfc_data.atqa[0] = 0x04;
+                nfc_data.atqa[1] = 0x00;
+                nfc_data.sak = 0x08;
+                nfc_data.uid_len = 0x04;
             } else if(app->card == MifareCardClassic4k) {
-                nfc_dev_data.atqa[0] = 0x02;
-                nfc_dev_data.atqa[1] = 0x00;
-                nfc_dev_data.sak = 0x18;
-                nfc_dev_data.uid_len = 0x04;
+                nfc_data.atqa[0] = 0x02;
+                nfc_data.atqa[1] = 0x00;
+                nfc_data.sak = 0x18;
+                nfc_data.uid_len = 0x04;
             } else if(app->card == MifareCardUltralight) {
-                nfc_dev_data.atqa[0] = 0x44;
-                nfc_dev_data.atqa[1] = 0x00;
-                nfc_dev_data.sak = 0x00;
-                nfc_dev_data.uid_len = 0x07;
+                nfc_data.atqa[0] = 0x44;
+                nfc_data.atqa[1] = 0x00;
+                nfc_data.sak = 0x00;
+                nfc_data.uid_len = 0x07;
             }
 
             // Set UIDs
             if(app->attack == MifareFuzzerAttackTestValues) {
                 // Load test UIDs
-                for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) {
-                    nfc_dev_data.uid[i] = id_uid_test[attack_step][i];
+                for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
+                    nfc_data.uid[i] = id_uid_test[attack_step][i];
                 }
                 // Next UIDs on next loop
                 if(attack_step >= 8) {
@@ -121,13 +123,13 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
 
                     // TODO: Manufacture-code must be selectable from a list
                     // use a fixed manufacture-code for now: 0x04 = NXP Semiconductors Germany
-                    nfc_dev_data.uid[0] = 0x04;
-                    for(uint8_t i = 1; i < nfc_dev_data.uid_len; i++) {
-                        nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF);
+                    nfc_data.uid[0] = 0x04;
+                    for(uint8_t i = 1; i < nfc_data.uid_len; i++) {
+                        nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
                     }
                 } else {
-                    for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) {
-                        nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF);
+                    for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
+                        nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
                     }
                 }
             } else if(app->attack == MifareFuzzerAttackLoadUidsFromFile) {
@@ -155,21 +157,21 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
 
                 // parse string to UID
                 // TODO: a better validation on input?
-                for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) {
+                for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
                     if(i <= ((furi_string_size(app->uid_str) - 1) / 2)) {
                         char temp_str[3];
                         temp_str[0] = furi_string_get_cstr(app->uid_str)[i * 2];
                         temp_str[1] = furi_string_get_cstr(app->uid_str)[i * 2 + 1];
                         temp_str[2] = '\0';
-                        nfc_dev_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
+                        nfc_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
                     } else {
-                        nfc_dev_data.uid[i] = 0x00;
+                        nfc_data.uid[i] = 0x00;
                     }
                 }
             }
 
-            mifare_fuzzer_worker_set_nfc_dev_data(app->worker, nfc_dev_data);
-            mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data);
+            mifare_fuzzer_worker_set_nfc_data(app->worker, nfc_data);
+            mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, nfc_data);
 
             // Reset tick_counter
             tick_counter = 0;

+ 5 - 5
mifare_fuzzer/views/mifare_fuzzer_emulator.c

@@ -39,12 +39,12 @@ static void mifare_fuzzer_emulator_draw_callback(Canvas* canvas, void* _model) {
     char uid[25];
     char uid_char[3];
     cpos = 0;
-    for(uint8_t i = 0; i < model->nfc_dev_data.uid_len; i++) {
+    for(uint8_t i = 0; i < model->nfc_data.uid_len; i++) {
         if(i > 0) {
             uid[cpos] = ':';
             cpos++;
         }
-        snprintf(uid_char, sizeof(uid_char), "%02X", model->nfc_dev_data.uid[i]);
+        snprintf(uid_char, sizeof(uid_char), "%02X", model->nfc_data.uid[i]);
         uid[cpos] = uid_char[0];
         cpos++;
         uid[cpos] = uid_char[1];
@@ -258,15 +258,15 @@ void mifare_fuzzer_emulator_set_attack(
 /// @brief mifare_fuzzer_emulator_set_nfc_dev_data
 /// @param mifare_fuzzer_emulator
 /// @param nfc_dev_data
-void mifare_fuzzer_emulator_set_nfc_dev_data(
+void mifare_fuzzer_emulator_set_nfc_data(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,
-    FuriHalNfcDevData nfc_dev_data) {
+    Iso14443_3aData nfc_data) {
     furi_assert(mifare_fuzzer_emulator);
 
     with_view_model(
         mifare_fuzzer_emulator->view,
         MifareFuzzerEmulatorModel * model,
-        { model->nfc_dev_data = nfc_dev_data; },
+        { model->nfc_data = nfc_data; },
         true);
 }
 

+ 5 - 3
mifare_fuzzer/views/mifare_fuzzer_emulator.h

@@ -5,6 +5,8 @@
 #include <gui/view.h>
 #include <gui/elements.h>
 
+#include "lib/nfc/protocols/iso14443_3a/iso14443_3a.h"
+
 typedef void (*MifareFuzzerEmulatorCallback)(MifareFuzzerEvent event, void* context);
 
 typedef enum MifareCard {
@@ -33,7 +35,7 @@ typedef struct MifareFuzzerEmulatorModel {
     const char* mifare_card_dsc;
     MifareFuzzerAttack attack;
     const char* attack_dsc;
-    FuriHalNfcDevData nfc_dev_data;
+    Iso14443_3aData nfc_data;
     bool is_attacking;
     uint8_t tick_num;
     uint8_t ticks_between_cards;
@@ -57,9 +59,9 @@ void mifare_fuzzer_emulator_set_callback(
     MifareFuzzerEmulatorCallback callback,
     void* context);
 
-void mifare_fuzzer_emulator_set_nfc_dev_data(
+void mifare_fuzzer_emulator_set_nfc_data(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,
-    FuriHalNfcDevData nfc_dev_data);
+    Iso14443_3aData nfc_data);
 
 void mifare_fuzzer_emulator_set_ticks_between_cards(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,

+ 0 - 0
wifisniffer/LICENSE → wardriver/LICENSE


+ 7 - 7
wifisniffer/application.fam → wardriver/application.fam

@@ -1,15 +1,15 @@
 App(
-    appid="wifisniffer",
-    name="[ESP32GPS] Wifi Sniff",
+    appid="wardriver",
+    name="[ESP32GPS] Wardriver",
     apptype=FlipperAppType.EXTERNAL,
-    entry_point="wifisniffer_app",
-    stack_size=2 * 1024,
-    fap_icon="sniff.png",
+    entry_point="wardriver_app",
+    stack_size=2048,
+    fap_icon="lookingglass.png",
     fap_category="WiFi",
     fap_author="@Sil333033",
-    fap_weburl="https://github.com/Flipper-XFW/Xtreme-Apps/tree/dev/wifisniffer",
+    fap_weburl="https://github.com/Flipper-XFW/Xtreme-Apps/tree/dev/wardriver",
     fap_version="1.0",
     fap_description="Sniff WiFi access points with GPS location coordinates",
     fap_icon_assets="icons",
-    fap_icon_assets_symbol="wifisniffer",
+    fap_icon_assets_symbol="wardriver",
 )

+ 0 - 0
wifisniffer/helpers/minmea.c → wardriver/helpers/minmea.c


+ 0 - 0
wifisniffer/helpers/minmea.h → wardriver/helpers/minmea.h


+ 0 - 0
wifisniffer/icons/down.png → wardriver/icons/down.png


+ 0 - 0
wifisniffer/icons/up.png → wardriver/icons/up.png


+ 0 - 0
wifisniffer/sniff.png → wardriver/lookingglass.png


+ 350 - 0
wardriver/wardriver.c

@@ -0,0 +1,350 @@
+#include "wardriver.h"
+#include "wardriver_uart.h"
+
+void save_file(Context* ctx) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    FuriHalRtcDateTime datetime;
+    furi_hal_rtc_get_datetime(&datetime);
+
+    FuriString* filename = furi_string_alloc();
+    furi_string_printf(
+        filename,
+        "%s/%s_%d_%d_%d_%d_%d_%d.txt",
+        FILE_PATH,
+        "wigle",
+        datetime.year,
+        datetime.month,
+        datetime.day,
+        datetime.hour,
+        datetime.minute,
+        datetime.second);
+
+    File* file = storage_file_alloc(storage);
+
+    if(!storage_common_exists(storage, FILE_PATH)) {
+        storage_common_mkdir(storage, FILE_PATH);
+    }
+
+    if(!storage_file_open(file, furi_string_get_cstr(filename), FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
+        FURI_LOG_I(appname, "Failed to open file");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_string_free(filename);
+        furi_record_close(RECORD_STORAGE);
+
+        furi_hal_light_blink_start(LightRed, 100, 100, 5000);
+
+        return;
+    }
+
+    furi_string_reset(ctx->buffer);
+
+    // WIGLE HEADERS DONT CHANGE THIS ITS IMPORTANT!
+    furi_string_printf(
+        ctx->buffer,
+        "%s,%s,%s,%s,%s,%s,%s,%s\r\n",
+        "WigleWifi-1.4",
+        "appRelease=v2.0",
+        "model=S33",
+        "release=XtremeFW",
+        "Flipper Zero",
+        "",
+        "Wardriver",
+        "S33");
+
+    furi_string_cat_printf(
+        ctx->buffer,
+        "%s,%s,%s,%s,%s,%s,%s\r\n",
+        "MAC",
+        "SSID",
+        "FirstSeen",
+        "Channel",
+        "RSSI",
+        "CurrentLatitude",
+        "CurrentLongitude");
+    if(!storage_file_write(
+           file, furi_string_get_cstr(ctx->buffer), strlen(furi_string_get_cstr(ctx->buffer)))) {
+        FURI_LOG_I(appname, "Failed to write header to file");
+    }
+
+    for(int i = 0; i < ctx->access_points_count; i++) {
+        AccessPoint ap = ctx->access_points[i];
+        furi_string_printf(
+            ctx->buffer,
+            "%s,%s,%04d-%02d-%02d %02d:%02d:%02d,%d,%d,%f,%f\r\n",
+            ap.bssid,
+            ap.ssid,
+            ap.datetime.year,
+            ap.datetime.month,
+            ap.datetime.day,
+            ap.datetime.hour,
+            ap.datetime.minute,
+            ap.datetime.second,
+            ap.rssi,
+            ap.channel,
+            (double)ap.latitude,
+            (double)ap.longitude);
+
+        if(!storage_file_write(
+               file,
+               furi_string_get_cstr(ctx->buffer),
+               strlen(furi_string_get_cstr(ctx->buffer)))) {
+            FURI_LOG_I(appname, "Failed to write AP to file");
+        }
+
+        free(ap.ssid);
+        free(ap.bssid);
+    }
+
+    storage_file_close(file);
+    storage_file_free(file);
+    furi_string_free(filename);
+    furi_record_close(RECORD_STORAGE);
+
+    return;
+}
+
+static void tick_callback(void* ctx_q) {
+    furi_assert(ctx_q);
+    FuriMessageQueue* queue = ctx_q;
+    Event event = {.type = EventTypeTick};
+    furi_message_queue_put(queue, &event, 0);
+}
+
+static void input_callback(InputEvent* input_event, FuriMessageQueue* queue) {
+    furi_assert(queue);
+    Event event = {.type = EventTypeKey, .input = *input_event};
+    furi_message_queue_put(queue, &event, FuriWaitForever);
+}
+
+static void draw_access_point(Canvas* canvas, Context* context) {
+    Context* ctx = context;
+
+    AccessPoint ap = ctx->active_access_point;
+
+    canvas_draw_str_aligned(canvas, 62, 25, AlignCenter, AlignBottom, ap.ssid);
+
+    canvas_set_font(canvas, FontSecondary);
+
+    canvas_draw_str_aligned(canvas, 38, 12, AlignLeft, AlignBottom, ap.bssid);
+
+    furi_string_printf(ctx->buffer, "Signal strength: %ddBm", ap.rssi);
+    canvas_draw_str_aligned(
+        canvas, 3, 35, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
+
+    furi_string_printf(ctx->buffer, "CH: %d", ap.channel);
+    canvas_draw_str_aligned(
+        canvas, 3, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
+
+    furi_string_printf(ctx->buffer, "%d", ap.packetRxCount);
+    canvas_draw_icon(canvas, 35, 39, &I_down);
+    canvas_draw_str_aligned(
+        canvas, 45, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
+
+    furi_string_printf(ctx->buffer, "%d", ap.packetTxCount);
+    canvas_draw_icon(canvas, 85, 38, &I_up);
+    canvas_draw_str_aligned(
+        canvas, 95, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
+
+    furi_string_printf(
+        ctx->buffer,
+        "Seen: %02d:%02d:%02d (%lds ago)",
+        ap.datetime.hour,
+        ap.datetime.minute,
+        ap.datetime.second,
+        furi_hal_rtc_get_timestamp() - furi_hal_rtc_datetime_to_timestamp(&ap.datetime));
+    canvas_draw_str_aligned(
+        canvas, 3, 59, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
+}
+
+static void render_callback(Canvas* canvas, void* context) {
+    Context* ctx = context;
+
+    canvas_set_font(canvas, FontPrimary);
+
+    if(ctx->access_points_count >= MAX_ACCESS_POINTS) {
+        canvas_draw_str(canvas, 118, 10, "!");
+    }
+
+    switch(ctx->view_state) {
+    case SHOW_NMEA:
+
+        if(UART_CH_ESP == UART_CH_GPS) {
+            canvas_draw_str(canvas, 0, 10, "GPS channel invalid!");
+            canvas_draw_str(canvas, 0, 20, "Change UART");
+            canvas_draw_str(canvas, 0, 30, "channel");
+            canvas_draw_str(canvas, 0, 40, "in the Xtreme");
+            canvas_draw_str(canvas, 0, 50, "app");
+        } else {
+            furi_string_printf(
+                ctx->buffer,
+                "%f",
+                isnan(ctx->gps_data.latitude) ? 0 : (double)ctx->gps_data.latitude);
+            canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(ctx->buffer));
+
+            furi_string_printf(
+                ctx->buffer,
+                "%f",
+                isnan(ctx->gps_data.longitude) ? 0 : (double)ctx->gps_data.longitude);
+            canvas_draw_str(canvas, 0, 20, furi_string_get_cstr(ctx->buffer));
+
+            furi_string_printf(ctx->buffer, "%d sats", ctx->gps_data.satelites);
+            canvas_draw_str(canvas, 0, 30, furi_string_get_cstr(ctx->buffer));
+
+            furi_string_printf(
+                ctx->buffer,
+                "%02d:%02d:%02dZ",
+                ctx->gps_data.hour,
+                ctx->gps_data.minute,
+                ctx->gps_data.second);
+            canvas_draw_str(canvas, 0, 40, furi_string_get_cstr(ctx->buffer));
+            canvas_draw_str(canvas, 70, 10, "GPS DATA");
+        }
+
+        elements_button_left(canvas, "Back");
+
+        canvas_draw_icon(canvas, 71, 15, &I_DolphinCommon_56x48);
+        break;
+    case NO_APS:
+        canvas_draw_str(canvas, 80, 30, "No AP's");
+        canvas_draw_str(canvas, 80, 40, "Found!");
+        canvas_draw_icon(canvas, 1, 4, &I_DolphinWait_61x59);
+        break;
+    case NORMAL:
+    default:
+        canvas_draw_frame(canvas, 0, 0, 128, 64);
+
+        furi_string_printf(
+            ctx->buffer, "%d/%d", ctx->access_points_index + 1, ctx->access_points_count);
+
+        canvas_draw_str(canvas, 3, 12, furi_string_get_cstr(ctx->buffer));
+
+        draw_access_point(canvas, ctx);
+        break;
+    }
+    furi_mutex_release(ctx->mutex);
+}
+
+int32_t wardriver_app() {
+    // turn off 5v, so it gets reset on startup
+    if(furi_hal_power_is_otg_enabled()) {
+        furi_hal_power_disable_otg();
+    }
+
+    // Enable 5v on startup
+    uint8_t attempts = 0;
+    while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
+        furi_hal_power_enable_otg();
+        furi_delay_ms(10);
+    }
+    furi_delay_ms(200);
+
+    Context* ctx = malloc(sizeof(Context));
+    ctx->queue = furi_message_queue_alloc(8, sizeof(Event));
+    ctx->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+    ctx->buffer = furi_string_alloc();
+
+    ctx->access_points_count = 0;
+    ctx->access_points_index = 0;
+    ctx->pressedButton = false;
+    ctx->view_state = NO_APS;
+
+    wardriver_uart_init(ctx);
+
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, render_callback, ctx);
+    view_port_input_callback_set(view_port, input_callback, ctx->queue);
+
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+    FuriTimer* timer = furi_timer_alloc(tick_callback, FuriTimerTypePeriodic, ctx->queue);
+    furi_timer_start(timer, 100);
+
+    // application loop
+    Event event;
+    bool processing = true;
+    do {
+        if(furi_message_queue_get(ctx->queue, &event, FuriWaitForever) == FuriStatusOk) {
+            furi_mutex_acquire(ctx->mutex, FuriWaitForever);
+            switch(event.type) {
+            case EventTypeKey:
+                if(event.input.type == InputTypeShort && event.input.key == InputKeyBack) {
+                    if(ctx->view_state == SHOW_NMEA) {
+                        ctx->view_state = NORMAL;
+                    } else {
+                        processing = false;
+                    }
+                } else if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
+                    if(ctx->view_state == SHOW_NMEA) {
+                        ctx->view_state = NORMAL;
+                    } else {
+                        processing = false;
+                    }
+                } else if(event.input.type == InputTypeLong && event.input.key == InputKeyOk) {
+                } else if(event.input.type == InputTypePress && event.input.key == InputKeyDown) {
+                    ctx->access_points_index--;
+                    if(ctx->access_points_index < 0) {
+                        ctx->access_points_index = ctx->access_points_count - 1;
+                    }
+                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
+                    ctx->pressedButton = true;
+                } else if(event.input.type == InputTypePress && event.input.key == InputKeyUp) {
+                    ctx->access_points_index++;
+                    if(ctx->access_points_index >= ctx->access_points_count) {
+                        ctx->access_points_index = 0;
+                    }
+                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
+                    ctx->pressedButton = true;
+                } else if(event.input.type == InputTypePress && event.input.key == InputKeyLeft) {
+                    if(ctx->view_state == NORMAL) {
+                        ctx->view_state = SHOW_NMEA;
+                    } else if(ctx->view_state == SHOW_NMEA) {
+                        ctx->view_state = NORMAL;
+                    }
+                } else if(event.input.type == InputTypePress && event.input.key == InputKeyRight) {
+                }
+                break;
+            case EventTypeTick:
+                // fix for the empty active access point when there was no interaction
+                if(!ctx->pressedButton) {
+                    ctx->access_points_index = 0;
+                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
+                }
+
+                break;
+            default:
+                break;
+            }
+
+            view_port_update(view_port);
+        } else {
+            processing = false;
+        }
+    } while(processing);
+
+    furi_timer_free(timer);
+    view_port_enabled_set(view_port, false);
+    gui_remove_view_port(gui, view_port);
+    view_port_free(view_port);
+    furi_record_close(RECORD_GUI);
+
+    furi_message_queue_free(ctx->queue);
+    furi_mutex_free(ctx->mutex);
+    furi_string_free(ctx->buffer);
+
+    wardriver_uart_deinit(ctx);
+
+    save_file(ctx);
+
+    free(ctx);
+
+    furi_hal_light_set(LightBlue, 0);
+    furi_hal_light_set(LightGreen, 0);
+
+    if(furi_hal_power_is_otg_enabled()) {
+        furi_hal_power_disable_otg();
+    }
+
+    return 0;
+}

+ 84 - 0
wardriver/wardriver.h

@@ -0,0 +1,84 @@
+#pragma once
+#include <furi.h>
+#include <furi_hal.h>
+#include <gui/gui.h>
+#include <gui/elements.h>
+#include <notification/notification_messages.h>
+#include <assets_icons.h>
+#include <toolbox/stream/file_stream.h>
+#include <xtreme.h>
+
+#include "helpers/minmea.h"
+#include "wardriver_icons.h"
+
+#define appname "ll-wardriver"
+
+#define RX_BUF_SIZE 2048
+#define MAX_ACCESS_POINTS 2048
+
+#define MAX_SSID_LENGTH 32
+#define MAX_BSSID_LENGTH 18
+
+#define FILE_PATH EXT_PATH("apps_data/ll-wardriver")
+
+typedef enum {
+    EventTypeKey,
+    EventTypeTick,
+} EventType;
+
+typedef struct {
+    EventType type;
+    InputEvent input;
+} Event;
+
+typedef enum { SHOW_NMEA, NORMAL, NO_APS } ViewState;
+
+typedef struct {
+    char* recievedMac;
+    char* sentMac;
+} Packet;
+
+typedef struct {
+    char* ssid;
+    char* bssid;
+    int8_t rssi;
+    uint8_t channel;
+    FuriHalRtcDateTime datetime;
+    uint16_t packetRxCount;
+    uint16_t packetTxCount;
+    float latitude;
+    float longitude;
+} AccessPoint;
+
+typedef struct {
+    float latitude;
+    float longitude;
+    uint8_t hour;
+    uint8_t minute;
+    uint8_t second;
+    uint8_t satelites;
+} GpsData;
+
+typedef struct {
+    FuriMessageQueue* queue;
+    FuriMutex* mutex;
+    FuriString* buffer;
+
+    FuriThread* thread_esp;
+    FuriStreamBuffer* rx_stream_esp;
+    uint8_t rx_buf_esp[2048];
+
+    FuriThread* thread_gps;
+    FuriStreamBuffer* rx_stream_gps;
+    uint8_t rx_buf_gps[2048];
+
+    uint16_t access_points_count;
+    AccessPoint access_points[MAX_ACCESS_POINTS];
+    int16_t access_points_index;
+    AccessPoint active_access_point;
+    bool extra_info;
+    bool pressedButton;
+
+    ViewState view_state;
+    GpsData gps_data;
+} Context;

+ 56 - 412
wifisniffer/sniffer.c → wardriver/wardriver_uart.c

@@ -1,176 +1,23 @@
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <notification/notification_messages.h>
-#include <assets_icons.h>
-#include <toolbox/stream/file_stream.h>
-#include <xtreme.h>
-
-#include "helpers/minmea.h"
-#include "wifisniffer_icons.h"
-
-#define appname "ll-wifisniffer"
-
-#define RX_BUF_SIZE 2048
-#define MAX_ACCESS_POINTS 2048 // imagine getting this many access points
-
-#define MAX_SSID_LENGTH 32
-#define MAX_BSSID_LENGTH 18
-
-#define UART_CH_ESP \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
-
-#define UART_CH_GPS \
-    (xtreme_settings.uart_nmea_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
-
-#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
-
-typedef enum {
-    WorkerEvtStop = (1 << 0),
-    WorkerEvtRxDone = (1 << 1),
-} WorkerEvtFlags;
-
-typedef enum {
-    EventTypeKey,
-    EventTypeTick,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} Event;
-
-typedef struct {
-    char* recievedMac;
-    char* sentMac;
-} Packet;
-
-typedef struct {
-    char* ssid;
-    char* bssid;
-    int8_t rssi;
-    uint8_t channel;
-    FuriHalRtcDateTime datetime;
-    uint16_t packetRxCount;
-    uint16_t packetTxCount;
-    float latitude;
-    float longitude;
-} AccessPoint;
-
-typedef struct {
-    FuriMessageQueue* queue;
-    FuriMutex* mutex;
-    FuriString* buffer;
-    FuriString* buffer2;
-    NotificationApp* notifications;
-    FuriThread* thread_esp;
-    FuriStreamBuffer* rx_stream_esp;
-    uint8_t rx_buf_esp[2048];
-    FuriThread* thread_gps;
-    FuriStreamBuffer* rx_stream_gps;
-    uint8_t rx_buf_gps[2048];
-    File* file;
-    char* dataString;
-    uint16_t access_points_count;
-    AccessPoint access_points[MAX_ACCESS_POINTS];
-    int16_t access_points_index;
-    AccessPoint active_access_point;
-    bool extra_info;
-    bool pressedButton;
-    float last_latitude;
-    float last_longitude;
-} Context;
-
-static void tick_callback(void* ctx_q) {
-    furi_assert(ctx_q);
-    FuriMessageQueue* queue = ctx_q;
-    Event event = {.type = EventTypeTick};
-    furi_message_queue_put(queue, &event, 0);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* queue) {
-    furi_assert(queue);
-    Event event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(queue, &event, FuriWaitForever);
-}
-
-static void show_access_point(Canvas* canvas, Context* context) {
-    Context* ctx = context;
-
-    AccessPoint ap = ctx->active_access_point;
-
-    canvas_draw_str_aligned(canvas, 62, 25, AlignCenter, AlignBottom, ap.ssid);
+#include "wardriver_uart.h"
 
-    canvas_set_font(canvas, FontSecondary);
-
-    canvas_draw_str_aligned(
-        canvas, 38 + (ctx->access_points_count > 99 ? 5 : 0), 12, AlignLeft, AlignBottom, ap.bssid);
-
-    furi_string_printf(ctx->buffer, "Signal strength: %ddBm", ap.rssi);
-    canvas_draw_str_aligned(
-        canvas, 3, 35, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
-
-    furi_string_printf(ctx->buffer, "CH: %d", ap.channel);
-    canvas_draw_str_aligned(
-        canvas, 3, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
-
-    if(ap.latitude == 0 && ap.longitude == 0) {
-        canvas_draw_str_aligned(canvas, 29, 47, AlignLeft, AlignBottom, "X");
-    } else {
-        canvas_draw_str_aligned(canvas, 29, 47, AlignLeft, AlignBottom, "O");
+static void removeSpaces(char* str) {
+    int i = 0;
+    while(isspace((unsigned char)str[i])) {
+        i++;
     }
 
-    furi_string_printf(ctx->buffer, "%d", ap.packetRxCount);
-    canvas_draw_icon(canvas, 35, 39, &I_down);
-    canvas_draw_str_aligned(
-        canvas, 45, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
-
-    furi_string_printf(ctx->buffer, "%d", ap.packetTxCount);
-    canvas_draw_icon(canvas, 85, 38, &I_up);
-    canvas_draw_str_aligned(
-        canvas, 95, 47, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
-
-    furi_string_printf(
-        ctx->buffer,
-        "Seen: %d:%d:%d (%lds ago)",
-        ap.datetime.hour,
-        ap.datetime.minute,
-        ap.datetime.second,
-        furi_hal_rtc_get_timestamp() - furi_hal_rtc_datetime_to_timestamp(&ap.datetime));
-    canvas_draw_str_aligned(
-        canvas, 3, 59, AlignLeft, AlignBottom, furi_string_get_cstr(ctx->buffer));
-}
-
-static void render_callback(Canvas* canvas, void* context) {
-    Context* ctx = context;
-
-    canvas_draw_frame(canvas, 0, 0, 128, 64);
-
-    canvas_set_font(canvas, FontPrimary);
-
-    if(ctx->access_points_count >= MAX_ACCESS_POINTS) {
-        canvas_draw_str(canvas, 118, 10, "!");
+    int j = 0;
+    while(str[i] != '\0') {
+        str[j++] = str[i++];
     }
+    str[j] = '\0';
 
-    if(ctx->access_points_count == 0) {
-        canvas_draw_str(canvas, 80, 30, "No AP's");
-        canvas_draw_str(canvas, 80, 40, "Found!");
-        canvas_draw_icon(canvas, 1, 4, &I_DolphinWait_61x59);
-    } else {
-        canvas_draw_frame(canvas, 0, 0, 35 + (ctx->access_points_count > 99 ? 5 : 0), 15);
-
-        furi_string_printf(
-            ctx->buffer, "%d/%d", ctx->access_points_index + 1, ctx->access_points_count);
-
-        canvas_draw_str(canvas, 3, 12, furi_string_get_cstr(ctx->buffer));
-
-        show_access_point(canvas, ctx);
+    int len = strlen(str);
+    while(len > 0 && isspace((unsigned char)str[len - 1])) {
+        str[--len] = '\0';
     }
-    // canvas_clear(canvas);
-    furi_mutex_release(ctx->mutex);
 }
 
-// order ctx->access_points by ssid alphabetically
 static void sort_access_points(Context* ctx) {
     for(int i = 0; i < ctx->access_points_count; i++) {
         for(int j = i + 1; j < ctx->access_points_count; j++) {
@@ -183,7 +30,6 @@ static void sort_access_points(Context* ctx) {
     }
 }
 
-// set the index from the active access point
 static void set_index_from_access_points(Context* ctx) {
     for(int i = 0; i < ctx->access_points_count; i++) {
         if(ctx->access_points[i].bssid == ctx->active_access_point.bssid) {
@@ -193,28 +39,7 @@ static void set_index_from_access_points(Context* ctx) {
     }
 }
 
-static void removeSpaces(char* str) {
-    // Remove spaces from the beginning of the string
-    int i = 0;
-    while(isspace((unsigned char)str[i])) {
-        i++;
-    }
-
-    // Move the remaining characters to the beginning of the string
-    int j = 0;
-    while(str[i] != '\0') {
-        str[j++] = str[i++];
-    }
-    str[j] = '\0';
-
-    // Remove spaces from the end of the string
-    int len = strlen(str);
-    while(len > 0 && isspace((unsigned char)str[len - 1])) {
-        str[--len] = '\0';
-    }
-}
-
-static void parseLine(void* context, char* line) {
+static void uart_parse_esp(void* context, char* line) {
     Context* ctx = context;
 
     AccessPoint ap = {.ssid = malloc(MAX_SSID_LENGTH + 1), .bssid = malloc(MAX_BSSID_LENGTH + 1)};
@@ -224,8 +49,7 @@ static void parseLine(void* context, char* line) {
     char* token = strtok(line, ",");
     int i = 0;
     bool isAp = false;
-    bool isValid = true;
-    UNUSED(isValid);
+    bool isValid = false;
     while(token != NULL) {
         switch(i) {
         case 0:
@@ -233,7 +57,6 @@ static void parseLine(void* context, char* line) {
                 isAp = true;
                 isValid = true;
             } else if(strcmp(token, "PK") == 0) {
-                isAp = false;
                 isValid = true;
             }
             break;
@@ -275,6 +98,10 @@ static void parseLine(void* context, char* line) {
         free(pkt.recievedMac);
         free(pkt.sentMac);
 
+        if(ctx->view_state == NO_APS) {
+            ctx->view_state = NORMAL;
+        }
+
         // check if values are valid
         // bssid needs an ":"
         // rssi needs to be negative
@@ -293,12 +120,12 @@ static void parseLine(void* context, char* line) {
 
         furi_hal_rtc_get_datetime(&ap.datetime);
 
-        if(isnan(ctx->last_latitude) || isnan(ctx->last_longitude)) {
-            ctx->last_latitude = 0;
-            ctx->last_longitude = 0;
+        if(isnan(ctx->gps_data.latitude) || isnan(ctx->gps_data.longitude)) {
+            ap.latitude = 0;
+            ap.longitude = 0;
         } else {
-            ap.latitude = ctx->last_latitude;
-            ap.longitude = ctx->last_longitude;
+            ap.latitude = ctx->gps_data.latitude;
+            ap.longitude = ctx->gps_data.longitude;
         }
 
         // check if ap is already in the list otherwise add it but update the rssi
@@ -426,7 +253,7 @@ static int32_t uart_worker_esp(void* context) {
                             // put a null terminator in place of the newline, to delimit the line string
                             *newline = '\0';
 
-                            parseLine(ctx, line_current);
+                            uart_parse_esp(ctx, line_current);
 
                             // move the cursor to the character after the newline
                             line_current = newline + 1;
@@ -451,36 +278,41 @@ static int32_t uart_worker_esp(void* context) {
         }
     }
 
-    furi_hal_uart_set_irq_cb(UART_CH_ESP, NULL, NULL);
-
-    furi_stream_buffer_free(ctx->rx_stream_esp);
-
     return 0;
 }
 
-static void gps_uart_parse_nmea(Context* ctx, char* line) {
+static void uart_parse_gps(Context* ctx, char* line) {
     switch(minmea_sentence_id(line, false)) {
     case MINMEA_SENTENCE_RMC: {
         struct minmea_sentence_rmc frame;
         if(minmea_parse_rmc(&frame, line)) {
-            ctx->last_latitude = minmea_tocoord(&frame.latitude);
-            ctx->last_longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
+            ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.hour = frame.time.hours;
+            ctx->gps_data.minute = frame.time.minutes;
+            ctx->gps_data.second = frame.time.seconds;
         }
     } break;
-
     case MINMEA_SENTENCE_GGA: {
         struct minmea_sentence_gga frame;
         if(minmea_parse_gga(&frame, line)) {
-            ctx->last_latitude = minmea_tocoord(&frame.latitude);
-            ctx->last_longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
+            ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.hour = frame.time.hours;
+            ctx->gps_data.minute = frame.time.minutes;
+            ctx->gps_data.second = frame.time.seconds;
+            ctx->gps_data.satelites = frame.satellites_tracked;
         }
     } break;
 
     case MINMEA_SENTENCE_GLL: {
         struct minmea_sentence_gll frame;
         if(minmea_parse_gll(&frame, line)) {
-            ctx->last_latitude = minmea_tocoord(&frame.latitude);
-            ctx->last_longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
+            ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
+            ctx->gps_data.hour = frame.time.hours;
+            ctx->gps_data.minute = frame.time.minutes;
+            ctx->gps_data.second = frame.time.seconds;
         }
     } break;
 
@@ -544,9 +376,7 @@ static int32_t uart_worker_gps(void* context) {
                             // put a null terminator in place of the newline, to delimit the line string
                             *newline = '\0';
 
-                            // FURI_LOG_I(appname, "Received line: %s", line_current);
-
-                            gps_uart_parse_nmea(ctx, line_current);
+                            uart_parse_gps(ctx, line_current);
 
                             // move the cursor to the character after the newline
                             line_current = newline + 1;
@@ -571,52 +401,14 @@ static int32_t uart_worker_gps(void* context) {
         }
     }
 
-    furi_hal_uart_set_irq_cb(UART_CH_GPS, NULL, NULL);
-
-    furi_stream_buffer_free(ctx->rx_stream_gps);
-
     return 0;
 }
 
-int32_t wifisniffer_app(void* p) {
-    UNUSED(p);
-
-    // if(UART_CH_ESP == UART_CH_GPS) {
-    //     FURI_LOG_I(appname, "ESP and GPS uart can't be the same");
-    //     return -1;
-    // }
-
-    // turn off 5v, so it gets reset on startup
-    if(furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_disable_otg();
-    }
-
-    // Enable 5v on startup
-    uint8_t attempts = 0;
-    while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
-        furi_hal_power_enable_otg();
-        furi_delay_ms(10);
-    }
-    furi_delay_ms(200);
-
-    // alloc everything
-    Context* ctx = malloc(sizeof(Context));
-    ctx->queue = furi_message_queue_alloc(8, sizeof(Event));
-    ctx->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    ctx->buffer = furi_string_alloc();
-    ctx->buffer2 = furi_string_alloc();
-    ctx->notifications = furi_record_open(RECORD_NOTIFICATION);
-
-    ctx->access_points_count = 0;
-    ctx->access_points_index = 0;
-
-    ctx->pressedButton = false;
-
-    //esp uart
-    ctx->rx_stream_esp = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1);
+void wardriver_uart_init(Context* ctx) {
+    ctx->rx_stream_esp = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
 
     ctx->thread_esp = furi_thread_alloc();
-    furi_thread_set_name(ctx->thread_esp, "LLwifiSnifferUartWorkerESP");
+    furi_thread_set_name(ctx->thread_esp, "LLwardriverUartWorkerESP");
     furi_thread_set_stack_size(ctx->thread_esp, 2048);
     furi_thread_set_context(ctx->thread_esp, ctx);
     furi_thread_set_callback(ctx->thread_esp, uart_worker_esp);
@@ -631,15 +423,11 @@ int32_t wifisniffer_app(void* p) {
     furi_hal_uart_set_br(UART_CH_ESP, 115200);
     furi_hal_uart_set_irq_cb(UART_CH_ESP, uart_cb_esp, ctx);
 
-    furi_hal_uart_tx(UART_CH_ESP, (uint8_t*)"XFW#WIFISNIFF=1\r\n", strlen("XFW#WIFISNIFF=1\r\n"));
-    //end esp uart
-
-    //gps uart
     if(UART_CH_ESP != UART_CH_GPS) {
-        ctx->rx_stream_gps = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1);
+        ctx->rx_stream_gps = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
 
         ctx->thread_gps = furi_thread_alloc();
-        furi_thread_set_name(ctx->thread_gps, "LLwifiSnifferUartWorkerGPS");
+        furi_thread_set_name(ctx->thread_gps, "LLwardriverUartWorkerGPS");
         furi_thread_set_stack_size(ctx->thread_gps, 2048);
         furi_thread_set_context(ctx->thread_gps, ctx);
         furi_thread_set_callback(ctx->thread_gps, uart_worker_gps);
@@ -654,165 +442,25 @@ int32_t wifisniffer_app(void* p) {
         furi_hal_uart_set_br(UART_CH_GPS, 9600);
         furi_hal_uart_set_irq_cb(UART_CH_GPS, uart_cb_gps, ctx);
     }
-    //end gps uart
-
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, ctx);
-    view_port_input_callback_set(view_port, input_callback, ctx->queue);
-
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    FuriTimer* timer = furi_timer_alloc(tick_callback, FuriTimerTypePeriodic, ctx->queue);
-    furi_timer_start(timer, 100);
-
-    // application loop
-    Event event;
-    bool processing = true;
-    do {
-        if(furi_message_queue_get(ctx->queue, &event, FuriWaitForever) == FuriStatusOk) {
-            furi_mutex_acquire(ctx->mutex, FuriWaitForever);
-            switch(event.type) {
-            case EventTypeKey:
-                // applicatie verlaten
-                if(event.input.type == InputTypeShort && event.input.key == InputKeyBack) {
-                    processing = false;
-                } else if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
-                    processing = false;
-                } else if(event.input.type == InputTypeLong && event.input.key == InputKeyOk) {
-                    // remove accespoint
-                    if(ctx->access_points_count > 0) {
-                        for(int i = ctx->access_points_index; i < ctx->access_points_count - 1;
-                            i++) {
-                            ctx->access_points[i] = ctx->access_points[i + 1];
-                        }
-                        ctx->access_points_count--;
-                        if(ctx->access_points_index >= ctx->access_points_count) {
-                            ctx->access_points_index = ctx->access_points_count - 1;
-                        }
-                    }
-                } else if(event.input.type == InputTypePress && event.input.key == InputKeyDown) {
-                    ctx->access_points_index--;
-                    if(ctx->access_points_index < 0) {
-                        ctx->access_points_index = ctx->access_points_count - 1;
-                    }
-                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
-                } else if(event.input.type == InputTypePress && event.input.key == InputKeyUp) {
-                    ctx->access_points_index++;
-                    if(ctx->access_points_index >= ctx->access_points_count) {
-                        ctx->access_points_index = 0;
-                    }
-                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
-                } else if(event.input.type == InputTypePress && event.input.key == InputKeyLeft) {
-                } else if(event.input.type == InputTypePress && event.input.key == InputKeyRight) {
-                }
-                ctx->pressedButton = true;
-                break;
-            case EventTypeTick:
-
-                // fix for the empty active access point when there was no interaction
-                if(!ctx->pressedButton) {
-                    ctx->access_points_index = 0;
-                    ctx->active_access_point = ctx->access_points[ctx->access_points_index];
-                }
-
-                break;
-
-            default:
-                break;
-            }
-
-            view_port_update(view_port);
-        } else {
-            processing = false;
-        }
-    } while(processing);
-
-    // save the data to the file
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FuriHalRtcDateTime datetime;
-    furi_hal_rtc_get_datetime(&datetime);
-
-    FuriString* filename = furi_string_alloc();
-    furi_string_printf(
-        filename,
-        "%d_%d_%d_%d_%d_%d.txt",
-        datetime.year,
-        datetime.month,
-        datetime.day,
-        datetime.hour,
-        datetime.minute,
-        datetime.second);
-
-    FuriString* path = furi_string_alloc();
-    furi_string_printf(path, "/ext/apps_data/llsniffer/%s", furi_string_get_cstr(filename));
-
-    // open file
-    ctx->file = storage_file_alloc(storage);
-
-    if(!storage_common_exists(storage, EXT_PATH("apps_data/llsniffer"))) {
-        storage_common_mkdir(storage, EXT_PATH("apps_data/llsniffer"));
-    }
-
-    if(!storage_file_open(ctx->file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
-        FURI_LOG_E(appname, "Failed to open file");
-    }
 
-    for(int i = 0; i < ctx->access_points_count; i++) {
-        AccessPoint ap = ctx->access_points[i];
-        furi_string_printf(
-            ctx->buffer2,
-            "%s,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f\r\n",
-            "Accesspoint",
-            ap.ssid,
-            ap.bssid,
-            ap.rssi,
-            ap.channel,
-            ap.datetime.year,
-            ap.datetime.month,
-            ap.datetime.day,
-            ap.datetime.hour,
-            ap.datetime.minute,
-            ap.datetime.second,
-            (double)ap.latitude,
-            (double)ap.longitude);
-
-        if(!storage_file_write(
-               ctx->file,
-               furi_string_get_cstr(ctx->buffer2),
-               strlen(furi_string_get_cstr(ctx->buffer2)))) {
-            FURI_LOG_E(appname, "Failed to write AP to file");
-        }
-    }
-
-    // free everything
-    furi_record_close(RECORD_NOTIFICATION);
-    furi_timer_free(timer);
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    view_port_free(view_port);
-    furi_record_close(RECORD_GUI);
-    furi_message_queue_free(ctx->queue);
-    furi_mutex_free(ctx->mutex);
+    return;
+}
 
+void wardriver_uart_deinit(Context* ctx) {
     furi_thread_flags_set(furi_thread_get_id(ctx->thread_esp), WorkerEvtStop);
     furi_thread_join(ctx->thread_esp);
     furi_thread_free(ctx->thread_esp);
+    furi_hal_uart_set_irq_cb(UART_CH_ESP, NULL, NULL);
+    furi_stream_buffer_free(ctx->rx_stream_esp);
 
     if(UART_CH_ESP != UART_CH_GPS) {
         furi_thread_flags_set(furi_thread_get_id(ctx->thread_gps), WorkerEvtStop);
         furi_thread_join(ctx->thread_gps);
         furi_thread_free(ctx->thread_gps);
+        furi_hal_uart_set_irq_cb(UART_CH_GPS, NULL, NULL);
+        furi_stream_buffer_free(ctx->rx_stream_gps);
     }
 
-    storage_file_close(ctx->file);
-    storage_file_free(ctx->file);
-    furi_record_close(RECORD_STORAGE);
-    free(ctx);
-
-    furi_hal_light_set(LightBlue, 0);
-    furi_hal_light_set(LightGreen, 0);
-
     if(UART_CH_ESP == FuriHalUartIdLPUART1) {
         furi_hal_uart_deinit(UART_CH_ESP);
     } else if(UART_CH_ESP == FuriHalUartIdUSART1) {
@@ -825,9 +473,5 @@ int32_t wifisniffer_app(void* p) {
         furi_hal_console_enable();
     }
 
-    if(furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_disable_otg();
-    }
-
-    return 0;
-}
+    return;
+}

+ 17 - 0
wardriver/wardriver_uart.h

@@ -0,0 +1,17 @@
+#include "wardriver.h"
+
+#define UART_CH_ESP \
+    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+
+#define UART_CH_GPS \
+    (xtreme_settings.uart_nmea_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+
+#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
+
+typedef enum {
+    WorkerEvtStop = (1 << 0),
+    WorkerEvtRxDone = (1 << 1),
+} WorkerEvtFlags;
+
+void wardriver_uart_init(Context* ctx);
+void wardriver_uart_deinit(Context* ctx);