Forráskód Böngészése

uArT rEfAcToRiNg!1!! (jk its better now)

Willy-JL 2 éve
szülő
commit
55abecde15
68 módosított fájl, 623 hozzáadás és 611 törlés
  1. 25 33
      camera_suite/views/camera_suite_view_camera.c
  2. 4 4
      camera_suite/views/camera_suite_view_camera.h
  3. 30 30
      dap_link/dap_link.c
  4. 13 13
      dap_link/usb/dap_v2_usb.c
  5. 14 18
      esp8266_deauth/esp8266_deauth.c
  6. 20 19
      esp_flasher/esp_flasher_uart.c
  7. 3 3
      esp_flasher/esp_flasher_uart.h
  8. 3 3
      esp_flasher/esp_flasher_worker.c
  9. 2 1
      evil_portal/evil_portal_app.c
  10. 1 2
      evil_portal/evil_portal_app_i.h
  11. 15 20
      evil_portal/evil_portal_uart.c
  12. 1 1
      evil_portal/evil_portal_uart.h
  13. 18 11
      evil_portal/scenes/evil_portal_scene_console_output.c
  14. 3 3
      gpio_reader_b/scenes/gpio_scene_usb_uart_config.c
  15. 15 17
      gpio_reader_b/usb_uart_bridge.c
  16. 4 2
      gps_nmea/gps.c
  17. 12 17
      gps_nmea/gps_uart.c
  18. 2 2
      gps_nmea/gps_uart.h
  19. 3 4
      hc_sr04/hc_sr04.c
  20. 14 4
      ifttt/ifttt_virtual_button.c
  21. 3 1
      ifttt/ifttt_virtual_button.h
  22. 8 8
      ifttt/views/send_view.c
  23. 1 0
      magspoof/mag_i.h
  24. 9 9
      magspoof/scenes/mag_scene_read.c
  25. 1 1
      magspoof/scenes/mag_scene_read.h
  26. 15 10
      mayhem_camera/camera.c
  27. 3 2
      mayhem_camera/camera.h
  28. 6 6
      mayhem_marauder/scenes/wifi_marauder_scene_console_output.c
  29. 59 54
      mayhem_marauder/script/wifi_marauder_script_executor.c
  30. 2 1
      mayhem_marauder/script/wifi_marauder_script_worker.c
  31. 1 0
      mayhem_marauder/script/wifi_marauder_script_worker.h
  32. 5 5
      mayhem_marauder/wifi_marauder_app.c
  33. 23 25
      mayhem_marauder/wifi_marauder_uart.c
  34. 1 2
      mayhem_marauder/wifi_marauder_uart.h
  35. 3 3
      mayhem_morseflash/scenes/uart_terminal_scene_console_output.c
  36. 5 9
      mayhem_morseflash/uart_terminal_app.c
  37. 1 1
      mayhem_morseflash/uart_terminal_app_i.h
  38. 15 16
      mayhem_morseflash/uart_terminal_uart.c
  39. 1 1
      mayhem_morseflash/uart_terminal_uart.h
  40. 12 8
      mayhem_motion/uart_echo.c
  41. 3 2
      mayhem_motion/uart_echo.h
  42. 12 8
      mayhem_nannycam/uart_echo.c
  43. 3 2
      mayhem_nannycam/uart_echo.h
  44. 12 8
      mayhem_qrcode/uart_echo.c
  45. 3 2
      mayhem_qrcode/uart_echo.h
  46. 6 6
      nrf24batch/nrf24batch.c
  47. 6 6
      sentry_safe/sentry_safe.c
  48. 10 8
      uart_terminal/scenes/uart_terminal_scene_console_output.c
  49. 15 17
      uart_terminal/uart_terminal_uart.c
  50. 1 1
      uart_terminal/uart_terminal_uart.h
  51. 0 1
      uhf_rfid/uhf_app.c
  52. 21 13
      uhf_rfid/uhf_module.c
  53. 1 0
      uhf_rfid/uhf_module.h
  54. 2 0
      wardriver/wardriver.h
  55. 19 29
      wardriver/wardriver_uart.c
  56. 2 4
      wardriver/wardriver_uart.h
  57. 3 3
      wifi_deauther/scenes/wifi_deauther_scene_console_output.c
  58. 1 2
      wifi_deauther/wifi_deauther_app_i.h
  59. 15 19
      wifi_deauther/wifi_deauther_uart.c
  60. 1 1
      wifi_deauther/wifi_deauther_uart.h
  61. 11 9
      wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c
  62. 52 47
      wifi_marauder_companion/script/wifi_marauder_script_executor.c
  63. 2 1
      wifi_marauder_companion/script/wifi_marauder_script_worker.c
  64. 1 0
      wifi_marauder_companion/script/wifi_marauder_script_worker.h
  65. 20 23
      wifi_marauder_companion/wifi_marauder_uart.c
  66. 1 1
      wifi_marauder_companion/wifi_marauder_uart.h
  67. 1 2
      wifi_scanner/FlipperZeroWiFiModuleDefines.h
  68. 23 27
      wifi_scanner/wifi_scanner.c

+ 25 - 33
camera_suite/views/camera_suite_view_camera.c

@@ -196,7 +196,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
                     UNUSED(model);
 
                     // Stop camera stream.
-                    furi_hal_uart_tx(UART_CH, (uint8_t[]){'s'}, 1);
+                    furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'s'}, 1);
                     furi_delay_ms(50);
 
                     // Go back to the main menu.
@@ -217,13 +217,13 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
 
                     if(model->is_inverted) {
                         // Camera: Set invert to false on the ESP32-CAM.
-                        furi_hal_uart_tx(UART_CH, (uint8_t[]){'i'}, 1);
+                        furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'i'}, 1);
                         furi_delay_ms(50);
 
                         model->is_inverted = false;
                     } else {
                         // Camera: Set invert to true on the ESP32-CAM.
-                        furi_hal_uart_tx(UART_CH, (uint8_t[]){'I'}, 1);
+                        furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'I'}, 1);
                         furi_delay_ms(50);
 
                         model->is_inverted = true;
@@ -246,13 +246,13 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
 
                     if(model->is_dithering_enabled) {
                         // Camera: Disable dithering.
-                        furi_hal_uart_tx(UART_CH, (uint8_t[]){'d'}, 1);
+                        furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'d'}, 1);
                         furi_delay_ms(50);
 
                         model->is_dithering_enabled = false;
                     } else {
                         // Camera: Enable dithering.
-                        furi_hal_uart_tx(UART_CH, (uint8_t[]){'D'}, 1);
+                        furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'D'}, 1);
                         furi_delay_ms(50);
 
                         model->is_dithering_enabled = true;
@@ -276,7 +276,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
                     camera_suite_led_set_rgb(instance->context, 0, 0, 255);
 
                     // Camera: Increase contrast.
-                    furi_hal_uart_tx(UART_CH, (uint8_t[]){'C'}, 1);
+                    furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'C'}, 1);
                     furi_delay_ms(50);
 
                     instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context);
@@ -297,7 +297,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
                     camera_suite_led_set_rgb(instance->context, 0, 0, 255);
 
                     // Camera: Reduce contrast.
-                    furi_hal_uart_tx(UART_CH, (uint8_t[]){'c'}, 1);
+                    furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'c'}, 1);
                     furi_delay_ms(50);
 
                     instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context);
@@ -316,7 +316,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
                     camera_suite_led_set_rgb(instance->context, 0, 0, 255);
 
                     // @todo - Save picture directly to ESP32-CAM.
-                    // furi_hal_uart_tx(UART_CH, (uint8_t[]){'P'}, 1);
+                    // furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'P'}, 1);
 
                     // Save currently displayed image to the Flipper Zero SD card.
                     save_image_to_flipper_sd_card(model);
@@ -349,22 +349,22 @@ static void camera_suite_view_camera_enter(void* context) {
     CameraSuite* instance_context = instance->context;
 
     // Start camera stream.
-    furi_hal_uart_tx(UART_CH, (uint8_t[]){'S'}, 1);
+    furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'S'}, 1);
     furi_delay_ms(50);
 
     // Get/set dither type.
     uint8_t dither_type = instance_context->dither;
-    furi_hal_uart_tx(UART_CH, &dither_type, 1);
+    furi_hal_serial_tx(instance->serial_handle, &dither_type, 1);
     furi_delay_ms(50);
 
     // Make sure the camera is not inverted.
-    furi_hal_uart_tx(UART_CH, (uint8_t[]){'i'}, 1);
+    furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'i'}, 1);
     furi_delay_ms(50);
 
     // Toggle flash on or off based on the current state. If the user has this
     // on the flash will stay on the entire time the user is in the camera view.
     uint8_t flash_state = instance_context->flash ? 'F' : 'f';
-    furi_hal_uart_tx(UART_CH, &flash_state, 1);
+    furi_hal_serial_tx(instance->serial_handle, &flash_state, 1);
     furi_delay_ms(50);
 
     with_view_model(
@@ -374,9 +374,9 @@ static void camera_suite_view_camera_enter(void* context) {
         true);
 }
 
-static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* context) {
-    furi_assert(uartIrqEvent);
-    furi_assert(data);
+static void
+    camera_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
+    furi_assert(handle);
     furi_assert(context);
 
     // Cast `context` to `CameraSuiteViewCamera*` and store it in `instance`.
@@ -384,7 +384,8 @@ static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* cont
 
     // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the
     // `rx_stream` and set the `WorkerEventRx` flag.
-    if(uartIrqEvent == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(instance->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(instance->worker_thread), WorkerEventRx);
     }
@@ -512,18 +513,13 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() {
     instance->worker_thread = thread;
     furi_thread_start(instance->worker_thread);
 
-    // Enable uart listener
-    if(UART_CH == UART_CH) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, 230400);
-    }
-
     // 115200 is the default baud rate for the ESP32-CAM.
-    furi_hal_uart_set_br(UART_CH, 230400);
+    instance->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(instance->serial_handle);
+    furi_hal_serial_init(instance->serial_handle, 230400);
 
     // Enable UART1 and set the IRQ callback.
-    furi_hal_uart_set_irq_cb(UART_CH, camera_on_irq_cb, instance);
+    furi_hal_serial_async_rx_start(instance->serial_handle, camera_on_irq_cb, instance, false);
 
     return instance;
 }
@@ -531,21 +527,17 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() {
 void camera_suite_view_camera_free(CameraSuiteViewCamera* instance) {
     furi_assert(instance);
 
-    // Remove the IRQ callback.
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
-
     // Free the worker thread.
+    furi_thread_flags_set(furi_thread_get_id(instance->worker_thread), WorkerEventStop);
+    furi_thread_join(instance->worker_thread);
     furi_thread_free(instance->worker_thread);
 
     // Free the allocated stream buffer.
     furi_stream_buffer_free(instance->rx_stream);
 
     // Re-enable the console.
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(instance->serial_handle);
+    furi_hal_serial_control_release(instance->serial_handle);
 
     with_view_model(
         instance->view, UartDumpModel * model, { UNUSED(model); }, true);

+ 4 - 4
camera_suite/views/camera_suite_view_camera.h

@@ -2,8 +2,8 @@
 
 #include <furi.h>
 #include <furi_hal.h>
-#include <furi_hal_console.h>
-#include <furi_hal_uart.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/elements.h>
 #include <gui/gui.h>
 #include <gui/icon_i.h>
@@ -19,8 +19,7 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 
 #define BITMAP_HEADER_LENGTH 62
 #define FRAME_BIT_DEPTH 1
@@ -52,6 +51,7 @@ typedef void (*CameraSuiteViewCameraCallback)(CameraSuiteCustomEvent event, void
 typedef struct CameraSuiteViewCamera {
     CameraSuiteViewCameraCallback callback;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
     FuriThread* worker_thread;
     NotificationApp* notification;
     View* view;

+ 30 - 30
dap_link/dap_link.c

@@ -2,8 +2,8 @@
 #include <furi.h>
 #include <furi_hal_version.h>
 #include <furi_hal_gpio.h>
-#include <furi_hal_uart.h>
-#include <furi_hal_console.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <furi_hal_resources.h>
 #include <furi_hal_power.h>
 #include <stm32wbxx_ll_usart.h>
@@ -277,14 +277,15 @@ typedef enum {
 typedef struct {
     FuriStreamBuffer* rx_stream;
     FuriThreadId thread_id;
-    FuriHalUartId uart_id;
+    FuriHalSerialHandle* serial_handle;
     struct usb_cdc_line_coding line_coding;
 } CDCProcess;
 
-static void cdc_uart_irq_cb(UartIrqEvent ev, uint8_t data, void* ctx) {
+static void cdc_uart_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* ctx) {
     CDCProcess* app = ctx;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
         furi_thread_flags_set(app->thread_id, CdcThreadEventUartRx);
     }
@@ -318,54 +319,52 @@ static void cdc_usb_config_callback(struct usb_cdc_line_coding* config, void* co
     furi_thread_flags_set(app->thread_id, CdcThreadEventCdcConfig);
 }
 
-static FuriHalUartId cdc_init_uart(
+static void cdc_init_uart(
+    CDCProcess* app,
     DapUartType type,
     DapUartTXRX swap,
     uint32_t baudrate,
-    void (*cb)(UartIrqEvent ev, uint8_t data, void* ctx),
+    void (*cb)(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* ctx),
     void* ctx) {
-    FuriHalUartId uart_id = FuriHalUartIdUSART1;
     if(baudrate == 0) baudrate = 115200;
 
     switch(type) {
     case DapUartTypeUSART1:
-        uart_id = FuriHalUartIdUSART1;
-        furi_hal_console_disable();
-        furi_hal_uart_deinit(uart_id);
+        app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+        furi_check(app->serial_handle);
         if(swap == DapUartTXRXSwap) {
             LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_SWAPPED);
         } else {
             LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD);
         }
-        furi_hal_uart_init(uart_id, baudrate);
-        furi_hal_uart_set_irq_cb(uart_id, cb, ctx);
+        furi_hal_serial_init(app->serial_handle, baudrate);
+        furi_hal_serial_async_rx_start(app->serial_handle, cb, ctx, false);
         break;
     case DapUartTypeLPUART1:
-        uart_id = FuriHalUartIdLPUART1;
-        furi_hal_uart_deinit(uart_id);
+        app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdLpuart);
+        furi_check(app->serial_handle);
         if(swap == DapUartTXRXSwap) {
             LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_SWAPPED);
         } else {
             LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD);
         }
-        furi_hal_uart_init(uart_id, baudrate);
-        furi_hal_uart_set_irq_cb(uart_id, cb, ctx);
+        furi_hal_serial_init(app->serial_handle, baudrate);
+        furi_hal_serial_async_rx_start(app->serial_handle, cb, ctx, false);
         break;
     }
-
-    return uart_id;
 }
 
-static void cdc_deinit_uart(DapUartType type) {
+static void cdc_deinit_uart(CDCProcess* app, DapUartType type) {
     switch(type) {
     case DapUartTypeUSART1:
-        furi_hal_uart_deinit(FuriHalUartIdUSART1);
+        furi_hal_serial_deinit(app->serial_handle);
         LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD);
-        furi_hal_console_init();
+        furi_hal_serial_control_release(app->serial_handle);
         break;
     case DapUartTypeLPUART1:
-        furi_hal_uart_deinit(FuriHalUartIdLPUART1);
+        furi_hal_serial_deinit(app->serial_handle);
         LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD);
+        furi_hal_serial_control_release(app->serial_handle);
         break;
     }
 }
@@ -387,8 +386,8 @@ static int32_t dap_cdc_process(void* p) {
     const uint8_t rx_buffer_size = 64;
     uint8_t* rx_buffer = malloc(rx_buffer_size);
 
-    app->uart_id = cdc_init_uart(
-        uart_pins_prev, uart_swap_prev, dap_state->cdc_baudrate, cdc_uart_irq_cb, app);
+    cdc_init_uart(
+        app, uart_pins_prev, uart_swap_prev, dap_state->cdc_baudrate, cdc_uart_irq_cb, app);
 
     dap_cdc_usb_set_context(app);
     dap_cdc_usb_set_rx_callback(cdc_usb_rx_callback);
@@ -407,7 +406,7 @@ static int32_t dap_cdc_process(void* p) {
                 if(dap_state->cdc_baudrate != app->line_coding.dwDTERate) {
                     dap_state->cdc_baudrate = app->line_coding.dwDTERate;
                     if(dap_state->cdc_baudrate > 0) {
-                        furi_hal_uart_set_br(app->uart_id, dap_state->cdc_baudrate);
+                        furi_hal_serial_set_br(app->serial_handle, dap_state->cdc_baudrate);
                     }
                 }
             }
@@ -426,7 +425,7 @@ static int32_t dap_cdc_process(void* p) {
             if(events & CdcThreadEventCdcRx) {
                 size_t len = dap_cdc_usb_rx(rx_buffer, rx_buffer_size);
                 if(len > 0) {
-                    furi_hal_uart_tx(app->uart_id, rx_buffer, len);
+                    furi_hal_serial_tx(app->serial_handle, rx_buffer, len);
                 }
                 dap_state->cdc_tx_counter += len;
             }
@@ -434,10 +433,11 @@ static int32_t dap_cdc_process(void* p) {
             if(events & CdcThreadEventApplyConfig) {
                 if(uart_pins_prev != dap_app->config.uart_pins ||
                    uart_swap_prev != dap_app->config.uart_swap) {
-                    cdc_deinit_uart(uart_pins_prev);
+                    cdc_deinit_uart(app, uart_pins_prev);
                     uart_pins_prev = dap_app->config.uart_pins;
                     uart_swap_prev = dap_app->config.uart_swap;
-                    app->uart_id = cdc_init_uart(
+                    cdc_init_uart(
+                        app,
                         uart_pins_prev,
                         uart_swap_prev,
                         dap_state->cdc_baudrate,
@@ -458,7 +458,7 @@ static int32_t dap_cdc_process(void* p) {
         }
     }
 
-    cdc_deinit_uart(uart_pins_prev);
+    cdc_deinit_uart(app, uart_pins_prev);
     free(rx_buffer);
     furi_stream_buffer_free(app->rx_stream);
     free(app);

+ 13 - 13
dap_link/usb/dap_v2_usb.c

@@ -3,7 +3,7 @@
 #include <usb_std.h>
 #include <usb_hid.h>
 #include <usb_cdc.h>
-#include <furi_hal_console.h>
+#include <core/log.h>
 
 #include "dap_v2_usb.h"
 
@@ -484,8 +484,8 @@ void furi_console_log_printf(const char* format, ...) {
     va_start(args, format);
     vsnprintf(buffer, sizeof(buffer), format, args);
     va_end(args);
-    furi_hal_console_puts(buffer);
-    furi_hal_console_puts("\r\n");
+    furi_log_puts(buffer);
+    furi_log_puts("\r\n");
     UNUSED(format);
 }
 #else
@@ -800,41 +800,41 @@ static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) {
 static void dump_request_type(uint8_t type) {
     switch(type & USB_REQ_DIRECTION) {
     case USB_REQ_HOSTTODEV:
-        furi_hal_console_puts("host to dev, ");
+        furi_log_puts("host to dev, ");
         break;
     case USB_REQ_DEVTOHOST:
-        furi_hal_console_puts("dev to host, ");
+        furi_log_puts("dev to host, ");
         break;
     }
 
     switch(type & USB_REQ_TYPE) {
     case USB_REQ_STANDARD:
-        furi_hal_console_puts("standard, ");
+        furi_log_puts("standard, ");
         break;
     case USB_REQ_CLASS:
-        furi_hal_console_puts("class, ");
+        furi_log_puts("class, ");
         break;
     case USB_REQ_VENDOR:
-        furi_hal_console_puts("vendor, ");
+        furi_log_puts("vendor, ");
         break;
     }
 
     switch(type & USB_REQ_RECIPIENT) {
     case USB_REQ_DEVICE:
-        furi_hal_console_puts("device");
+        furi_log_puts("device");
         break;
     case USB_REQ_INTERFACE:
-        furi_hal_console_puts("interface");
+        furi_log_puts("interface");
         break;
     case USB_REQ_ENDPOINT:
-        furi_hal_console_puts("endpoint");
+        furi_log_puts("endpoint");
         break;
     case USB_REQ_OTHER:
-        furi_hal_console_puts("other");
+        furi_log_puts("other");
         break;
     }
 
-    furi_hal_console_puts("\r\n");
+    furi_log_puts("\r\n");
 }
 #else
 #define dump_request_type(...)

+ 14 - 18
esp8266_deauth/esp8266_deauth.c

@@ -1,8 +1,8 @@
 #include <furi.h>
-#include <furi_hal_console.h>
 #include <furi_hal_gpio.h>
 #include <furi_hal_power.h>
-#include <furi_hal_uart.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/canvas_i.h>
 #include <gui/gui.h>
 #include <input/input.h>
@@ -15,8 +15,7 @@
 
 #include "FlipperZeroWiFiDeauthModuleDefines.h"
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 
 #define DEAUTH_APP_DEBUG 0
 
@@ -69,6 +68,7 @@ typedef struct SWiFiDeauthApp {
     FuriThread* m_worker_thread;
     //NotificationApp* m_notification;
     FuriStreamBuffer* m_rx_stream;
+    FuriHalSerialHandle* serial_handle;
     SGpioButtons m_GpioButtons;
 
     bool m_wifiDeauthModuleInitialized;
@@ -213,14 +213,16 @@ static void
     furi_message_queue_put(event_queue, &event, FuriWaitForever);
 }
 
-static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    uart_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
 
     SWiFiDeauthApp* app = context;
 
     DEAUTH_APP_LOG_I("uart_echo_on_irq_cb");
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         DEAUTH_APP_LOG_I("ev == UartIrqEventRXNE");
         furi_stream_buffer_send(app->m_rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventRx);
@@ -391,13 +393,10 @@ int32_t esp8266_deauth_app(void* p) {
     DEAUTH_APP_LOG_I("UART thread allocated");
 
     // Enable uart listener
-    if(UART_CH == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, FLIPPERZERO_SERIAL_BAUD);
-    }
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, FLIPPERZERO_SERIAL_BAUD);
+    furi_hal_serial_async_rx_start(app->serial_handle, uart_on_irq_cb, app, false);
     DEAUTH_APP_LOG_I("UART Listener created");
 
     SPluginEvent event;
@@ -511,11 +510,8 @@ int32_t esp8266_deauth_app(void* p) {
     furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
     furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
 
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     //*app->m_originalBufferLocation = app->m_originalBuffer;
 

+ 20 - 19
esp_flasher/esp_flasher_uart.c

@@ -3,11 +3,11 @@
 
 struct EspFlasherUart {
     EspFlasherApp* app;
-    FuriHalUartId channel;
     FuriThread* rx_thread;
     FuriStreamBuffer* rx_stream;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef enum {
@@ -24,10 +24,14 @@ void esp_flasher_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void esp_flasher_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void esp_flasher_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     EspFlasherUart* uart = (EspFlasherUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
     }
@@ -49,22 +53,24 @@ static int32_t uart_worker(void* context) {
         }
     }
 
-    furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL);
     furi_stream_buffer_free(uart->rx_stream);
 
     return 0;
 }
 
-void esp_flasher_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void esp_flasher_uart_tx(EspFlasherUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
+}
+
+void esp_flasher_uart_set_br(EspFlasherUart* uart, uint32_t baud) {
+    furi_hal_serial_set_br(uart->serial_handle, baud);
 }
 
 EspFlasherUart*
-    esp_flasher_uart_init(EspFlasherApp* app, FuriHalUartId channel, const char* thread_name) {
+    esp_flasher_uart_init(EspFlasherApp* app, FuriHalSerialId channel, const char* thread_name) {
     EspFlasherUart* uart = malloc(sizeof(EspFlasherUart));
 
     uart->app = app;
-    uart->channel = channel;
     uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     uart->rx_thread = furi_thread_alloc();
     furi_thread_set_name(uart->rx_thread, thread_name);
@@ -72,13 +78,10 @@ EspFlasherUart*
     furi_thread_set_context(uart->rx_thread, uart);
     furi_thread_set_callback(uart->rx_thread, uart_worker);
     furi_thread_start(uart->rx_thread);
-    if(channel == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(channel, BAUDRATE);
-    }
-    furi_hal_uart_set_br(channel, BAUDRATE);
-    furi_hal_uart_set_irq_cb(channel, esp_flasher_uart_on_irq_cb, uart);
+    uart->serial_handle = furi_hal_serial_control_acquire(channel);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, esp_flasher_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -94,10 +97,8 @@ void esp_flasher_uart_free(EspFlasherUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    if(uart->channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(uart->channel);
-    }
-    furi_hal_console_enable();
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 3 - 3
esp_flasher/esp_flasher_uart.h

@@ -4,8 +4,7 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 #define BAUDRATE (115200)
 #define FAST_BAUDRATE (921600)
 
@@ -16,6 +15,7 @@ typedef struct EspFlasherUart EspFlasherUart;
 void esp_flasher_uart_set_handle_rx_data_cb(
     EspFlasherUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void esp_flasher_uart_tx(uint8_t* data, size_t len);
+void esp_flasher_uart_tx(EspFlasherUart* uart, uint8_t* data, size_t len);
+void esp_flasher_uart_set_br(EspFlasherUart* uart, uint32_t baud);
 EspFlasherUart* esp_flasher_usart_init(EspFlasherApp* app);
 void esp_flasher_uart_free(EspFlasherUart* uart);

+ 3 - 3
esp_flasher/esp_flasher_worker.c

@@ -237,7 +237,7 @@ static int32_t esp_flasher_flash_bin(void* context) {
                 err_msg, sizeof(err_msg), "Cannot change transmission rate. Error: %u\n", err);
             loader_port_debug_print(err_msg);
         }
-        furi_hal_uart_set_br(UART_CH, FAST_BAUDRATE);
+        esp_flasher_uart_set_br(app->uart, FAST_BAUDRATE);
     }
 
     if(!err) {
@@ -256,7 +256,7 @@ static int32_t esp_flasher_flash_bin(void* context) {
 
         if(app->turbospeed) {
             loader_port_debug_print("Restoring transmission rate\n");
-            furi_hal_uart_set_br(UART_CH, BAUDRATE);
+            esp_flasher_uart_set_br(app->uart, FAST_BAUDRATE);
         }
 
         loader_port_debug_print(
@@ -365,7 +365,7 @@ esp_loader_error_t loader_port_read(uint8_t* data, uint16_t size, uint32_t timeo
 
 esp_loader_error_t loader_port_write(const uint8_t* data, uint16_t size, uint32_t timeout) {
     UNUSED(timeout);
-    esp_flasher_uart_tx((uint8_t*)data, size);
+    if(global_app) esp_flasher_uart_tx(global_app->uart, (uint8_t*)data, size);
     return ESP_LOADER_SUCCESS;
 }
 

+ 2 - 1
evil_portal/evil_portal_app.c

@@ -83,7 +83,8 @@ Evil_PortalApp* evil_portal_app_alloc() {
 
 void evil_portal_app_free(Evil_PortalApp* app) {
     // Send reset event to dev board
-    evil_portal_uart_tx((uint8_t*)(RESET_CMD "\nstopscan\n"), strlen(RESET_CMD "\nstopscan\n"));
+    evil_portal_uart_tx(
+        app->uart, (uint8_t*)(RESET_CMD "\nstopscan\n"), strlen(RESET_CMD "\nstopscan\n"));
 
     furi_assert(app);
 

+ 1 - 2
evil_portal/evil_portal_app_i.h

@@ -21,8 +21,7 @@
 #define NUM_MENU_ITEMS (6)
 
 #define EVIL_PORTAL_TEXT_BOX_STORE_SIZE (4096)
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 
 #define SET_HTML_CMD "sethtml"
 #define SET_AP_CMD "setap"

+ 15 - 20
evil_portal/evil_portal_uart.c

@@ -11,6 +11,7 @@ struct Evil_PortalUart {
     uint8_t mark_test_idx;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef enum {
@@ -27,10 +28,14 @@ void evil_portal_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void evil_portal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void evil_portal_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     Evil_PortalUart* uart = (Evil_PortalUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         const char* mark_begin = "[BUF/BEGIN]";
         const char* mark_close = "[BUF/CLOSE]";
         if(uart->mark_test_idx != 0) {
@@ -122,14 +127,13 @@ static int32_t uart_worker(void* context) {
         }
     }
 
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
     furi_stream_buffer_free(uart->rx_stream);
 
     return 0;
 }
 
-void evil_portal_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void evil_portal_uart_tx(Evil_PortalUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
 Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app) {
@@ -145,19 +149,13 @@ Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app) {
 
     furi_thread_start(uart->rx_thread);
 
-    if(UART_CH == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, app->BAUDRATE);
-    }
-
     if(app->BAUDRATE == 0) {
         app->BAUDRATE = 115200;
     }
-    furi_hal_uart_set_br(UART_CH, app->BAUDRATE);
-    furi_hal_uart_set_irq_cb(UART_CH, evil_portal_uart_on_irq_cb, uart);
-
-    evil_portal_uart_tx((uint8_t*)("XFW#EVILPORTAL=1\n"), strlen("XFW#EVILPORTAL=1\n"));
+    uart->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, app->BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, evil_portal_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -169,11 +167,8 @@ void evil_portal_uart_free(Evil_PortalUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 1
evil_portal/evil_portal_uart.h

@@ -9,6 +9,6 @@ typedef struct Evil_PortalUart Evil_PortalUart;
 void evil_portal_uart_set_handle_rx_data_cb(
     Evil_PortalUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void evil_portal_uart_tx(uint8_t* data, size_t len);
+void evil_portal_uart_tx(Evil_PortalUart* uart, uint8_t* data, size_t len);
 Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app);
 void evil_portal_uart_free(Evil_PortalUart* uart);

+ 18 - 11
evil_portal/scenes/evil_portal_scene_console_output.c

@@ -120,7 +120,8 @@ void evil_portal_scene_console_output_on_enter(void* 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));
+            evil_portal_uart_tx(
+                app->uart, (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);
@@ -131,7 +132,7 @@ void evil_portal_scene_console_output_on_enter(void* context) {
                 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));
+                    app->uart, (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);
@@ -142,6 +143,7 @@ void evil_portal_scene_console_output_on_enter(void* context) {
             if(icanhazmarauder) {
                 furi_string_reset(app->captured_line);
                 evil_portal_uart_tx(
+                    app->uart,
                     (uint8_t*)("evilportal -c sethtmlstr\n"),
                     strlen("evilportal -c sethtmlstr\n"));
                 for(uint8_t t = 0; t < 10 && !captured(app, "\n>") &&
@@ -151,19 +153,24 @@ void evil_portal_scene_console_output_on_enter(void* context) {
                 // 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);
+                    evil_portal_uart_tx(
+                        app->uart, app->index_html, strlen((char*)app->index_html));
+                    evil_portal_uart_tx(app->uart, (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"));
+                        app->uart,
+                        (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);
+                    app->uart,
+                    (uint8_t*)(furi_string_get_cstr(data)),
+                    strlen(furi_string_get_cstr(data)));
+                evil_portal_uart_tx(app->uart, (uint8_t*)("\n"), 1);
             }
 
             free(app->index_html);
@@ -172,12 +179,12 @@ void evil_portal_scene_console_output_on_enter(void* context) {
             furi_string_free(data);
         } else if(0 == strncmp(RESET_CMD, app->selected_tx_string, strlen(RESET_CMD))) {
             evil_portal_uart_tx(
-                (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-            evil_portal_uart_tx((uint8_t*)("\nstopscan\n"), strlen("\nstopscan\n"));
+                app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+            evil_portal_uart_tx(app->uart, (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));
-            evil_portal_uart_tx((uint8_t*)("\n"), 1);
+                app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+            evil_portal_uart_tx(app->uart, (uint8_t*)("\n"), 1);
         }
     }
 }

+ 3 - 3
gpio_reader_b/scenes/gpio_scene_usb_uart_config.c

@@ -42,7 +42,7 @@ void line_ensure_flow_invariant(GpioApp* app) {
     // selected. This function enforces that invariant by resetting flow_pins
     // to None if it is configured to 16,15 when LPUART is selected.
 
-    uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalUartIdLPUART1 ? 3 : 4;
+    uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalSerialIdLpuart ? 3 : 4;
     VariableItem* item = app->var_item_flow;
     variable_item_set_values_count(item, available_flow_pins);
 
@@ -73,9 +73,9 @@ static void line_port_cb(VariableItem* item) {
     variable_item_set_current_value_text(item, uart_ch[index]);
 
     if(index == 0)
-        app->usb_uart_cfg->uart_ch = FuriHalUartIdUSART1;
+        app->usb_uart_cfg->uart_ch = FuriHalSerialIdUsart;
     else if(index == 1)
-        app->usb_uart_cfg->uart_ch = FuriHalUartIdLPUART1;
+        app->usb_uart_cfg->uart_ch = FuriHalSerialIdLpuart;
 
     line_ensure_flow_invariant(app);
     view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet);

+ 15 - 17
gpio_reader_b/usb_uart_bridge.c

@@ -43,6 +43,7 @@ struct UsbUartBridge {
 
     FuriThread* thread;
     FuriThread* tx_thread;
+    FuriHalSerialHandle* serial_handle;
 
     FuriStreamBuffer* rx_stream;
 
@@ -75,10 +76,12 @@ static const CdcCallbacks cdc_cb = {
 
 static int32_t usb_uart_tx_thread(void* context);
 
-static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    usb_uart_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     UsbUartBridge* usb_uart = (UsbUartBridge*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
     }
@@ -111,32 +114,27 @@ static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
 }
 
 static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) {
-    if(uart_ch == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(uart_ch == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(uart_ch, 115200);
-    }
-    furi_hal_uart_set_irq_cb(uart_ch, usb_uart_on_irq_cb, usb_uart);
+    usb_uart->serial_handle = furi_hal_serial_control_acquire(uart_ch);
+    furi_check(usb_uart->serial_handle);
+    furi_hal_serial_init(usb_uart->serial_handle, 115200);
+    furi_hal_serial_async_rx_start(usb_uart->serial_handle, usb_uart_on_irq_cb, usb_uart, false);
 }
 
 static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) {
-    UNUSED(usb_uart);
-    furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL);
-    if(uart_ch == FuriHalUartIdUSART1)
-        furi_hal_console_enable();
-    else if(uart_ch == FuriHalUartIdLPUART1)
-        furi_hal_uart_deinit(uart_ch);
+    UNUSED(uart_ch);
+    furi_hal_serial_deinit(usb_uart->serial_handle);
+    furi_hal_serial_control_release(usb_uart->serial_handle);
 }
 
 static void usb_uart_set_baudrate(UsbUartBridge* usb_uart, uint32_t baudrate) {
     if(baudrate != 0) {
-        furi_hal_uart_set_br(usb_uart->cfg.uart_ch, baudrate);
+        furi_hal_serial_set_br(usb_uart->serial_handle, baudrate);
         usb_uart->st.baudrate_cur = baudrate;
     } else {
         struct usb_cdc_line_coding* line_cfg =
             furi_hal_cdc_get_port_settings(usb_uart->cfg.vcp_ch);
         if(line_cfg->dwDTERate > 0) {
-            furi_hal_uart_set_br(usb_uart->cfg.uart_ch, line_cfg->dwDTERate);
+            furi_hal_serial_set_br(usb_uart->serial_handle, baudrate);
             usb_uart->st.baudrate_cur = line_cfg->dwDTERate;
         }
     }
@@ -298,7 +296,7 @@ static int32_t usb_uart_tx_thread(void* context) {
 
             if(len > 0) {
                 usb_uart->st.tx_cnt += len;
-                furi_hal_uart_tx(usb_uart->cfg.uart_ch, data, len);
+                furi_hal_serial_tx(usb_uart->serial_handle, data, len);
             }
         }
     }

+ 4 - 2
gps_nmea/gps.c

@@ -232,8 +232,10 @@ int32_t gps_app(void* p) {
                         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_hal_serial_tx(
+                            gps_uart->serial_handle,
+                            (uint8_t*)"$PMTK161,0*28\r\n",
+                            strlen("$PMTK161,0*28\r\n"));
 
                         furi_mutex_release(gps_uart->mutex);
                         view_port_update(view_port);

+ 12 - 17
gps_nmea/gps_uart.c

@@ -10,36 +10,31 @@ typedef enum {
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-static void gps_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    gps_uart_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     GpsUart* gps_uart = (GpsUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(gps_uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(gps_uart->thread), WorkerEvtRxDone);
     }
 }
 
 static void gps_uart_serial_init(GpsUart* gps_uart) {
-    if(UART_CH == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, gps_uart->baudrate);
-    }
-
-    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);
+    gps_uart->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(gps_uart->serial_handle);
+    furi_hal_serial_init(gps_uart->serial_handle, gps_uart->baudrate);
+    furi_hal_serial_async_rx_start(gps_uart->serial_handle, gps_uart_on_irq_cb, gps_uart, false);
 
-    furi_hal_uart_tx(UART_CH, (uint8_t*)"wakey wakey\r\n", strlen("wakey wakey\r\n"));
+    furi_hal_serial_tx(
+        gps_uart->serial_handle, (uint8_t*)"wakey wakey\r\n", strlen("wakey wakey\r\n"));
 }
 
 static void gps_uart_serial_deinit(GpsUart* gps_uart) {
     UNUSED(gps_uart);
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(gps_uart->serial_handle);
+    furi_hal_serial_control_release(gps_uart->serial_handle);
 }
 
 static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) {

+ 2 - 2
gps_nmea/gps_uart.h

@@ -5,8 +5,7 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_nmea_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_nmea_channel)
 
 #define RX_BUF_SIZE 1024
 
@@ -43,6 +42,7 @@ typedef struct {
     FuriThread* thread;
     FuriStreamBuffer* rx_stream;
     uint8_t rx_buf[RX_BUF_SIZE];
+    FuriHalSerialHandle* serial_handle;
 
     NotificationApp* notifications;
     uint32_t baudrate;

+ 3 - 4
hc_sr04/hc_sr04.c

@@ -5,7 +5,6 @@
 #include <furi.h>
 #include <furi_hal.h>
 #include <furi_hal_power.h>
-#include <furi_hal_console.h>
 #include <gui/gui.h>
 #include <input/input.h>
 #include <stdlib.h>
@@ -183,7 +182,7 @@ int32_t hc_sr04_app() {
 
     hc_sr04_state_init(plugin_state);
 
-    furi_hal_console_disable();
+    FuriHalSerialHandle* serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
 
     plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
     if(!plugin_state->mutex) {
@@ -191,7 +190,7 @@ int32_t hc_sr04_app() {
         if(furi_hal_power_is_otg_enabled()) {
             furi_hal_power_disable_otg();
         }
-        furi_hal_console_enable();
+        furi_hal_serial_control_release(serial_handle);
         furi_hal_power_suppress_charge_exit();
         furi_message_queue_free(event_queue);
         free(plugin_state);
@@ -260,7 +259,7 @@ int32_t hc_sr04_app() {
         GpioPullUp,
         GpioSpeedVeryHigh,
         GpioAltFn7USART1);
-    furi_hal_console_enable();
+    furi_hal_serial_control_release(serial_handle);
 
     view_port_enabled_set(view_port, false);
     gui_remove_view_port(gui, view_port);

+ 14 - 4
ifttt/ifttt_virtual_button.c

@@ -91,7 +91,10 @@ Settings* load_settings() {
     return settings;
 }
 
-void send_serial_command_config(ESerialCommand command, Settings* settings) {
+void send_serial_command_config(
+    FuriHalSerialHandle* serial_handle,
+    ESerialCommand command,
+    Settings* settings) {
     uint8_t data[1] = {0};
 
     char config_tmp[100];
@@ -126,7 +129,7 @@ void send_serial_command_config(ESerialCommand command, Settings* settings) {
             return;
         }
 
-        furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1);
+        furi_hal_serial_tx(serial_handle, data, 1);
     }
 }
 
@@ -155,6 +158,10 @@ VirtualButtonApp* ifttt_virtual_button_app_alloc(uint32_t first_scene) {
     app->gui = furi_record_open(RECORD_GUI);
     app->power = furi_record_open(RECORD_POWER);
 
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, FLIPPERZERO_SERIAL_BAUD);
+
     // View dispatcher
     app->view_dispatcher = view_dispatcher_alloc();
     app->scene_manager = scene_manager_alloc(&virtual_button_scene_handlers, app);
@@ -169,7 +176,7 @@ VirtualButtonApp* ifttt_virtual_button_app_alloc(uint32_t first_scene) {
     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
 
     // Views
-    app->sen_view = send_view_alloc();
+    app->sen_view = send_view_alloc(app->serial_handle);
     view_dispatcher_add_view(
         app->view_dispatcher, VirtualButtonAppViewSendView, send_view_get_view(app->sen_view));
 
@@ -212,6 +219,9 @@ void ifttt_virtual_button_app_free(VirtualButtonApp* app) {
     furi_record_close(RECORD_POWER);
     furi_record_close(RECORD_GUI);
 
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
+
     free(app);
 }
 
@@ -228,7 +238,7 @@ int32_t ifttt_virtual_button_app(void* p) {
     uint32_t first_scene = VirtualButtonAppSceneStart;
     VirtualButtonApp* app = ifttt_virtual_button_app_alloc(first_scene);
     memcpy(&app->settings, load_settings(), sizeof(Settings));
-    send_serial_command_config(ESerialCommand_Config, &(app->settings));
+    send_serial_command_config(app->serial_handle, ESerialCommand_Config, &(app->settings));
 
     view_dispatcher_run(app->view_dispatcher);
     ifttt_virtual_button_app_free(app);

+ 3 - 1
ifttt/ifttt_virtual_button.h

@@ -13,7 +13,8 @@
 #include <flipper_format/flipper_format.h>
 #include <flipper_format/flipper_format_i.h>
 #include <storage/storage.h>
-#include <furi_hal_uart.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include "scenes/virtual_button_scene.h"
 
 #define APP_NAME "[ESP8266] IFTTT Virtual Button"
@@ -43,6 +44,7 @@ typedef struct {
     DialogEx* dialog;
     PowerInfo info;
     Settings settings;
+    FuriHalSerialHandle* serial_handle;
 } VirtualButtonApp;
 
 typedef enum {

+ 8 - 8
ifttt/views/send_view.c

@@ -3,16 +3,16 @@
 #include <gui/elements.h>
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
-#include <furi_hal_uart.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <string.h>
 #include <stdio.h>
 
-#define FLIPPERZERO_SERIAL_BAUD 115200
-
 typedef enum ESerialCommand { ESerialCommand_Send } ESerialCommand;
 
 struct SendView {
     View* view;
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef struct {
@@ -26,7 +26,7 @@ static void Shake(void) {
     furi_record_close(RECORD_NOTIFICATION);
 }
 
-void send_serial_command_send(ESerialCommand command) {
+void send_serial_command_send(FuriHalSerialHandle* serial_handle, ESerialCommand command) {
     uint8_t data[1] = {0};
 
     char name[10] = "send";
@@ -40,7 +40,7 @@ void send_serial_command_send(ESerialCommand command) {
             return;
         };
 
-        furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1);
+        furi_hal_serial_tx(serial_handle, data, 1);
     }
 }
 
@@ -72,7 +72,7 @@ static void send_view_process(SendView* send_view, InputEvent* event) {
                 } else if(event->key == InputKeyRight) {
                     model->right_pressed = true;
                     Shake();
-                    send_serial_command_send(ESerialCommand_Send);
+                    send_serial_command_send(send_view->serial_handle, ESerialCommand_Send);
                 } else if(event->key == InputKeyOk) {
                 } else if(event->key == InputKeyBack) {
                 }
@@ -107,14 +107,14 @@ static bool send_view_input_callback(InputEvent* event, void* context) {
     return consumed;
 }
 
-SendView* send_view_alloc() {
+SendView* send_view_alloc(FuriHalSerialHandle* serial_handle) {
     SendView* send_view = malloc(sizeof(SendView));
     send_view->view = view_alloc();
+    send_view->serial_handle = serial_handle;
     view_set_context(send_view->view, send_view);
     view_allocate_model(send_view->view, ViewModelTypeLocking, sizeof(SendViewModel));
     view_set_draw_callback(send_view->view, send_view_draw_callback);
     view_set_input_callback(send_view->view, send_view_input_callback);
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD);
 
     return send_view;
 }

+ 1 - 0
magspoof/mag_i.h

@@ -79,6 +79,7 @@ typedef struct {
     FuriStreamBuffer* uart_rx_stream;
     uint8_t uart_rx_buf[UART_RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 
     char uart_text_input_store[UART_TERMINAL_TEXT_INPUT_STORE_SIZE + 1];
     FuriString* uart_text_box_store;

+ 9 - 9
magspoof/scenes/mag_scene_read.c

@@ -7,9 +7,10 @@
 
 #define TAG "MagSceneRead"
 
-void uart_callback(UartIrqEvent event, uint8_t data, void* context) {
+void uart_callback(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     Mag* mag = context;
-    if(event == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(mag->uart_rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtRxDone);
     }
@@ -93,10 +94,10 @@ void mag_scene_read_on_enter(void* context) {
     update_widgets(mag);
 
     // Initialize UART
-    // furi_hal_console_disable();
-    furi_hal_uart_deinit(FuriHalUartIdUSART1);
-    furi_hal_uart_init(FuriHalUartIdUSART1, 9600);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_callback, mag);
+    mag->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(mag->serial_handle);
+    furi_hal_serial_init(mag->serial_handle, 9600);
+    furi_hal_serial_async_rx_start(mag->serial_handle, uart_callback, mag, false);
     FURI_LOG_D(TAG, "UART initialized");
 
     mag->uart_rx_thread = furi_thread_alloc();
@@ -177,9 +178,8 @@ void mag_scene_read_on_exit(void* context) {
 
     furi_string_free(mag->uart_text_box_store);
 
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
-    furi_hal_uart_deinit(FuriHalUartIdUSART1);
-    // furi_hal_console_enable();
+    furi_hal_serial_deinit(mag->serial_handle);
+    furi_hal_serial_control_release(mag->serial_handle);
 
     notification_message(mag->notifications, &sequence_blink_stop);
 }

+ 1 - 1
magspoof/scenes/mag_scene_read.h

@@ -5,7 +5,7 @@
 #define UART_RX_BUF_SIZE (320)
 #define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096)
 #define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512)
-#define UART_CH (FuriHalUartIdUSART1)
+#define UART_CH (FuriHalSerialIdUsart)
 #define UART_BAUDRATE (9600)
 
 typedef enum {

+ 15 - 10
mayhem_camera/camera.c

@@ -24,7 +24,7 @@ static void camera_view_draw_callback(Canvas* canvas, void* _model) {
         {
           // Init marauder into stream mode
           uint8_t data[] = "\nstream\n";
-          furi_hal_uart_tx(FuriHalUartIdUSART1, data, sizeof(data));
+          furi_hal_serial_tx(app->serial_handle, data, sizeof(data));
         }*/
 
         canvas_draw_icon(canvas, 80, 21, &I_WarningDolphinFlip_45x42);
@@ -117,7 +117,8 @@ static bool camera_view_input_callback(InputEvent* event, void* context) {
         } else if(event->key == InputKeyOk) {
             save_image(context);
         }
-        furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1);
+        UartEchoApp* app = context;
+        furi_hal_serial_tx(app->serial_handle, data, 1);
     }
 
     return false;
@@ -128,11 +129,13 @@ static uint32_t camera_exit(void* context) {
     return VIEW_NONE;
 }
 
-static void camera_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    camera_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
     UartEchoApp* app = context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
     }
@@ -193,7 +196,7 @@ static int32_t camera_worker(void* context) {
                 length = furi_stream_buffer_receive(app->rx_stream, data, intended_data_size, 0);
 
                 if(length > 0) {
-                    //furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
+                    //furi_hal_serial_tx(app->serial_handle, data, length);
                     with_view_model(
                         app->view,
                         UartDumpModel * model,
@@ -254,9 +257,10 @@ static UartEchoApp* camera_app_alloc() {
     furi_thread_start(app->worker_thread);
 
     // Enable uart listener
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, camera_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, 230400);
+    furi_hal_serial_async_rx_start(app->serial_handle, camera_on_irq_cb, app, false);
 
     furi_hal_power_disable_external_3_3v();
     furi_hal_power_disable_otg();
@@ -265,7 +269,7 @@ static UartEchoApp* camera_app_alloc() {
     furi_hal_power_enable_otg();
     for(int i = 0; i < 2; i++) {
         furi_delay_ms(500);
-        furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'c'}, 1);
+        furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'c'}, 1);
     }
     furi_delay_ms(1);
     return app;
@@ -274,7 +278,8 @@ static UartEchoApp* camera_app_alloc() {
 static void camera_app_free(UartEchoApp* app) {
     furi_assert(app);
 
-    furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
     furi_thread_join(app->worker_thread);

+ 3 - 2
mayhem_camera/camera.h

@@ -14,8 +14,8 @@
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
 #include <gui/elements.h>
-#include <furi_hal_uart.h>
-#include <furi_hal_console.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/view_dispatcher.h>
 #include <gui/modules/dialog_ex.h>
 #include <storage/filesystem_api_defines.h>
@@ -51,6 +51,7 @@ typedef struct {
     View* view;
     FuriThread* worker_thread;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
 } UartEchoApp;
 
 struct UartDumpModel {

+ 6 - 6
mayhem_marauder/scenes/wifi_marauder_scene_console_output.c

@@ -157,11 +157,11 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
         // Send command with newline '\n'
         if(app->selected_tx_string) {
             wifi_marauder_uart_tx(
-                (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-            wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+                app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+            wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
             if(send_html && the_html) {
-                wifi_marauder_uart_tx(the_html, html_size);
-                wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+                wifi_marauder_uart_tx(app->uart, the_html, html_size);
+                wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
                 free(the_html);
                 send_html = false;
             }
@@ -169,7 +169,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
 
         // Run the script if the file with the script has been opened
         if(app->script != NULL) {
-            app->script_worker = wifi_marauder_script_worker_alloc();
+            app->script_worker = wifi_marauder_script_worker_alloc(app->uart);
             wifi_marauder_script_worker_start(app->script_worker, app->script);
         }
     }
@@ -195,7 +195,7 @@ void wifi_marauder_scene_console_output_on_exit(void* context) {
 
     // Automatically stop the scan when exiting view
     if(app->is_command) {
-        wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
+        wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n"));
         furi_delay_ms(50);
     }
 

+ 59 - 54
mayhem_marauder/script/wifi_marauder_script_executor.c

@@ -5,20 +5,20 @@ void _wifi_marauder_script_delay(WifiMarauderScriptWorker* worker, uint32_t dela
     for(uint32_t i = 0; i < delay_secs && worker->is_running; i++) furi_delay_ms(1000);
 }
 
-void _send_stop() {
+void _send_stop(WifiMarauderScriptWorker* worker) {
     const char stop_command[] = "stopscan\n";
-    wifi_marauder_uart_tx((uint8_t*)(stop_command), strlen(stop_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(stop_command), strlen(stop_command));
 }
 
-void _send_line_break() {
-    wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+void _send_line_break(WifiMarauderScriptWorker* worker) {
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1);
 }
 
-void _send_channel_select(int channel) {
+void _send_channel_select(WifiMarauderScriptWorker* worker, int channel) {
     char command[30];
-    _send_line_break();
+    _send_line_break(worker);
     snprintf(command, sizeof(command), "channel -s %d\n", channel);
-    wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
 }
 
 void _wifi_marauder_script_execute_scan(
@@ -27,7 +27,7 @@ void _wifi_marauder_script_execute_scan(
     char command[15];
     // Set channel
     if(stage->channel > 0) {
-        _send_channel_select(stage->channel);
+        _send_channel_select(worker, stage->channel);
     }
     // Start scan
     if(stage->type == WifiMarauderScriptScanTypeAp) {
@@ -35,12 +35,14 @@ void _wifi_marauder_script_execute_scan(
     } else {
         snprintf(command, sizeof(command), "scansta\n");
     }
-    wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
-void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage) {
+void _wifi_marauder_script_execute_select(
+    WifiMarauderScriptStageSelect* stage,
+    WifiMarauderScriptWorker* worker) {
     const char* select_type = NULL;
     switch(stage->type) {
     case WifiMarauderScriptSelectTypeAp:
@@ -79,61 +81,61 @@ void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage)
             command, sizeof(command), "select %s -f \"%s\"\n", select_type, stage->filter);
     }
 
-    wifi_marauder_uart_tx((uint8_t*)command, command_length);
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, command_length);
 }
 
 void _wifi_marauder_script_execute_deauth(
     WifiMarauderScriptStageDeauth* stage,
     WifiMarauderScriptWorker* worker) {
     const char attack_command[] = "attack -t deauth\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_probe(
     WifiMarauderScriptStageProbe* stage,
     WifiMarauderScriptWorker* worker) {
     const char attack_command[] = "attack -t probe\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_raw(
     WifiMarauderScriptStageSniffRaw* stage,
     WifiMarauderScriptWorker* worker) {
-    const char sniff_command[] = "sniffraw\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    const char sniff_command[] = "sniffraw -serial\n";
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_beacon(
     WifiMarauderScriptStageSniffBeacon* stage,
     WifiMarauderScriptWorker* worker) {
-    const char sniff_command[] = "sniffbeacon\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    const char sniff_command[] = "sniffbeacon -serial\n";
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_deauth(
     WifiMarauderScriptStageSniffDeauth* stage,
     WifiMarauderScriptWorker* worker) {
-    const char sniff_command[] = "sniffdeauth\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    const char sniff_command[] = "sniffdeauth -serial\n";
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_esp(
     WifiMarauderScriptStageSniffEsp* stage,
     WifiMarauderScriptWorker* worker) {
-    const char sniff_command[] = "sniffesp\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    const char sniff_command[] = "sniffesp -serial\n";
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_pmkid(
@@ -150,10 +152,10 @@ void _wifi_marauder_script_execute_sniff_pmkid(
                 len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d");
             }
 
-            len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n");
-            wifi_marauder_uart_tx((uint8_t*)attack_command, len);
+            len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n");
+            wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len);
             _wifi_marauder_script_delay(worker, stage->timeout);
-            _send_stop();
+            _send_stop(worker);
         }
     } else {
         char attack_command[50] = "sniffpmkid";
@@ -167,27 +169,27 @@ void _wifi_marauder_script_execute_sniff_pmkid(
         if(stage->force_deauth) {
             len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d");
         }
-        len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n");
-        wifi_marauder_uart_tx((uint8_t*)attack_command, len);
+        len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n");
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len);
         _wifi_marauder_script_delay(worker, stage->timeout);
-        _send_stop();
+        _send_stop(worker);
     }
 }
 
 void _wifi_marauder_script_execute_sniff_pwn(
     WifiMarauderScriptStageSniffPwn* stage,
     WifiMarauderScriptWorker* worker) {
-    const char sniff_command[] = "sniffpwn\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    const char sniff_command[] = "sniffpwn -serial\n";
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_beacon_list(
     WifiMarauderScriptStageBeaconList* stage,
     WifiMarauderScriptWorker* worker) {
     const char clearlist_command[] = "clearlist -s\n";
-    wifi_marauder_uart_tx((uint8_t*)(clearlist_command), strlen(clearlist_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(clearlist_command), strlen(clearlist_command));
 
     char command[100];
     char* ssid;
@@ -195,8 +197,8 @@ void _wifi_marauder_script_execute_beacon_list(
     for(int i = 0; i < stage->ssid_count; i++) {
         ssid = stage->ssids[i];
         snprintf(command, sizeof(command), "ssid -a -n \"%s\"", ssid);
-        wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
+        _send_line_break(worker);
     }
     if(stage->random_ssids > 0) {
         char add_random_command[50];
@@ -205,27 +207,30 @@ void _wifi_marauder_script_execute_beacon_list(
             sizeof(add_random_command),
             "ssid -a -r -g %d\n",
             stage->random_ssids);
-        wifi_marauder_uart_tx((uint8_t*)add_random_command, strlen(add_random_command));
+        wifi_marauder_uart_tx(
+            worker->uart, (uint8_t*)add_random_command, strlen(add_random_command));
     }
     const char attack_command[] = "attack -t beacon -l\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_beacon_ap(
     WifiMarauderScriptStageBeaconAp* stage,
     WifiMarauderScriptWorker* worker) {
     const char command[] = "attack -t beacon -a\n";
-    wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
-void _wifi_marauder_script_execute_exec(WifiMarauderScriptStageExec* stage) {
+void _wifi_marauder_script_execute_exec(
+    WifiMarauderScriptStageExec* stage,
+    WifiMarauderScriptWorker* worker) {
     if(stage->command != NULL) {
-        wifi_marauder_uart_tx((uint8_t*)stage->command, strlen(stage->command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)stage->command, strlen(stage->command));
+        _send_line_break(worker);
     }
 }
 
@@ -248,8 +253,8 @@ void wifi_marauder_script_execute_start(void* context) {
             sizeof(command),
             "settings -s EnableLED %s",
             script->enable_led ? "enable" : "disable");
-        wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
+        _send_line_break(worker);
     }
 
     // Enables or disables PCAP saving according to script settings
@@ -259,8 +264,8 @@ void wifi_marauder_script_execute_start(void* context) {
             sizeof(command),
             "settings -s SavePCAP %s",
             script->save_pcap ? "enable" : "disable");
-        wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
+        _send_line_break(worker);
     }
 }
 
@@ -274,7 +279,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co
         _wifi_marauder_script_execute_scan((WifiMarauderScriptStageScan*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeSelect:
-        _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data);
+        _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeDeauth:
         _wifi_marauder_script_execute_deauth((WifiMarauderScriptStageDeauth*)stage_data, worker);
@@ -315,7 +320,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co
             (WifiMarauderScriptStageBeaconAp*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeExec:
-        _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data);
+        _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeDelay:
         _wifi_marauder_script_execute_delay((WifiMarauderScriptStageDelay*)stage_data, worker);

+ 2 - 1
mayhem_marauder/script/wifi_marauder_script_worker.c

@@ -1,7 +1,7 @@
 #include "../wifi_marauder_app_i.h"
 #include "wifi_marauder_script_worker.h"
 
-WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() {
+WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(WifiMarauderUart* uart) {
     WifiMarauderScriptWorker* worker = malloc(sizeof(WifiMarauderScriptWorker));
     if(worker == NULL) {
         return NULL;
@@ -9,6 +9,7 @@ WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() {
     worker->callback_start = NULL;
     worker->callback_stage = NULL;
     worker->worker_thread = NULL;
+    worker->uart = uart;
     worker->is_running = false;
     return worker;
 }

+ 1 - 0
mayhem_marauder/script/wifi_marauder_script_worker.h

@@ -11,6 +11,7 @@ typedef enum {
 typedef struct WifiMarauderScriptWorker {
     WifiMarauderScript* script;
     FuriThread* worker_thread;
+    WifiMarauderUart* uart;
     void (*callback_start)(void*);
     void (*callback_stage)(WifiMarauderScriptStage*, void*);
     void* context;

+ 5 - 5
mayhem_marauder/wifi_marauder_app.c

@@ -177,11 +177,6 @@ int32_t wifi_marauder_app(void* p) {
         furi_delay_ms(10);
     }
     furi_delay_ms(200);
-    for(int i = 0; i < 2; i++) {
-        furi_delay_ms(500);
-        furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'w'}, 1);
-    }
-    furi_delay_ms(1);
 
     WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc();
 
@@ -190,6 +185,11 @@ int32_t wifi_marauder_app(void* p) {
 
     wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app);
     wifi_marauder_app->lp_uart = wifi_marauder_lp_uart_init(wifi_marauder_app);
+    for(int i = 0; i < 2; i++) {
+        furi_delay_ms(500);
+        wifi_marauder_uart_tx(wifi_marauder_app->uart, (uint8_t[1]){'w'}, 1);
+    }
+    furi_delay_ms(1);
 
     view_dispatcher_run(wifi_marauder_app->view_dispatcher);
 

+ 23 - 25
mayhem_marauder/wifi_marauder_uart.c

@@ -1,15 +1,15 @@
 #include "wifi_marauder_app_i.h"
 #include "wifi_marauder_uart.h"
 
-#define UART_CH (FuriHalUartIdUSART1)
-#define LP_UART_CH (FuriHalUartIdLPUART1)
+#define UART_CH (FuriHalSerialIdUsart)
+#define LP_UART_CH (FuriHalSerialIdLpuart)
 #define BAUDRATE (230400)
 
 struct WifiMarauderUart {
     WifiMarauderApp* app;
-    FuriHalUartId channel;
     FuriThread* rx_thread;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
 };
@@ -28,10 +28,14 @@ void wifi_marauder_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void wifi_marauder_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void wifi_marauder_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     WifiMarauderUart* uart = (WifiMarauderUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
     }
@@ -58,20 +62,17 @@ static int32_t uart_worker(void* context) {
     return 0;
 }
 
-void wifi_marauder_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
-void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(LP_UART_CH, data, len);
-}
-
-WifiMarauderUart*
-    wifi_marauder_uart_init(WifiMarauderApp* app, FuriHalUartId channel, const char* thread_name) {
+WifiMarauderUart* wifi_marauder_uart_init(
+    WifiMarauderApp* app,
+    FuriHalSerialId channel,
+    const char* thread_name) {
     WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart));
 
     uart->app = app;
-    uart->channel = channel;
     uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     uart->rx_thread = furi_thread_alloc();
     furi_thread_set_name(uart->rx_thread, thread_name);
@@ -79,13 +80,13 @@ WifiMarauderUart*
     furi_thread_set_context(uart->rx_thread, uart);
     furi_thread_set_callback(uart->rx_thread, uart_worker);
     furi_thread_start(uart->rx_thread);
-    if(channel == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(channel, BAUDRATE);
+    uart->serial_handle = furi_hal_serial_control_acquire(channel);
+    if(!uart->serial_handle) {
+        furi_delay_ms(5000);
     }
-    furi_hal_uart_set_br(channel, BAUDRATE);
-    furi_hal_uart_set_irq_cb(channel, wifi_marauder_uart_on_irq_cb, uart);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, wifi_marauder_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -105,11 +106,8 @@ void wifi_marauder_uart_free(WifiMarauderUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL);
-    if(uart->channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(uart->channel);
-    }
-    furi_hal_console_enable();
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 2
mayhem_marauder/wifi_marauder_uart.h

@@ -9,8 +9,7 @@ typedef struct WifiMarauderUart WifiMarauderUart;
 void wifi_marauder_uart_set_handle_rx_data_cb(
     WifiMarauderUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void wifi_marauder_uart_tx(uint8_t* data, size_t len);
-void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len);
+void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len);
 WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app);
 WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app);
 void wifi_marauder_uart_free(WifiMarauderUart* uart);

+ 3 - 3
mayhem_morseflash/scenes/uart_terminal_scene_console_output.c

@@ -64,8 +64,8 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
     // Send command with newline '\n'
     /*if(!app->is_command && app->selected_tx_string)*/ {
         uart_terminal_uart_tx(
-            (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-        uart_terminal_uart_tx((uint8_t*)("\n"), 1);
+            app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+        uart_terminal_uart_tx(app->uart, (uint8_t*)("\n"), 1);
     }
 }
 
@@ -92,6 +92,6 @@ void uart_terminal_scene_console_output_on_exit(void* context) {
 
     // Automatically logut when exiting view
     //if(app->is_command) {
-    //    uart_terminal_uart_tx((uint8_t*)("exit\n"), strlen("exit\n"));
+    //    uart_terminal_uart_tx(app->uart,(uint8_t*)("exit\n"), strlen("exit\n"));
     //}
 }

+ 5 - 9
mayhem_morseflash/uart_terminal_app.c

@@ -91,24 +91,20 @@ void uart_terminal_app_free(UART_TerminalApp* app) {
 int32_t uart_terminal_app(void* p) {
     UNUSED(p);
 
-    // Enable uart listener
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(UART_CH, BAUDRATE); // TODO: Clean this
-    //furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
-
     furi_hal_power_disable_external_3_3v();
     furi_hal_power_disable_otg();
     furi_delay_ms(200);
     furi_hal_power_enable_external_3_3v();
     furi_hal_power_enable_otg();
+    UART_TerminalApp* uart_terminal_app = uart_terminal_app_alloc();
+
+    uart_terminal_app->uart = uart_terminal_uart_init(uart_terminal_app);
+
     for(int i = 0; i < 2; i++) {
         furi_delay_ms(500);
-        furi_hal_uart_tx(UART_CH, (uint8_t[1]){'.'}, 1);
+        uart_terminal_uart_tx(uart_terminal_app->uart, (uint8_t[1]){'.'}, 1);
     }
     furi_delay_ms(1);
-    UART_TerminalApp* uart_terminal_app = uart_terminal_app_alloc();
-
-    uart_terminal_app->uart = uart_terminal_uart_init(uart_terminal_app);
 
     view_dispatcher_run(uart_terminal_app->view_dispatcher);
 

+ 1 - 1
mayhem_morseflash/uart_terminal_app_i.h

@@ -16,7 +16,7 @@
 
 #define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096)
 #define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512)
-#define UART_CH (FuriHalUartIdUSART1)
+#define UART_CH (FuriHalSerialIdUsart)
 #define BAUDRATE (230400)
 
 struct UART_TerminalApp {

+ 15 - 16
mayhem_morseflash/uart_terminal_uart.c

@@ -7,6 +7,7 @@ struct UART_TerminalUart {
     FuriStreamBuffer* rx_stream;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef enum {
@@ -23,10 +24,14 @@ void uart_terminal_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void uart_terminal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void uart_terminal_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     UART_TerminalUart* uart = (UART_TerminalUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
     }
@@ -53,20 +58,13 @@ static int32_t uart_worker(void* context) {
     return 0;
 }
 
-void uart_terminal_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
 UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) {
     UART_TerminalUart* uart = malloc(sizeof(UART_TerminalUart));
 
-    /*furi_hal_console_disable();
-    if(app->BAUDRATE == 0) {
-        app->BAUDRATE = 230400;
-    }
-    furi_hal_uart_set_br(UART_CH, app->BAUDRATE);
-    furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart);*/
-
     uart->app = app;
     uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     uart->rx_thread = furi_thread_alloc();
@@ -77,9 +75,10 @@ UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) {
 
     furi_thread_start(uart->rx_thread);
 
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(UART_CH, BAUDRATE);
-    furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart);
+    uart->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, uart_terminal_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -91,8 +90,8 @@ void uart_terminal_uart_free(UART_TerminalUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
-    furi_hal_console_enable();
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 1
mayhem_morseflash/uart_terminal_uart.h

@@ -9,6 +9,6 @@ typedef struct UART_TerminalUart UART_TerminalUart;
 void uart_terminal_uart_set_handle_rx_data_cb(
     UART_TerminalUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void uart_terminal_uart_tx(uint8_t* data, size_t len);
+void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len);
 UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app);
 void uart_terminal_uart_free(UART_TerminalUart* uart);

+ 12 - 8
mayhem_motion/uart_echo.c

@@ -40,11 +40,13 @@ static uint32_t uart_echo_exit(void* context) {
     return VIEW_NONE;
 }
 
-static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
     UartEchoApp* app = context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
     }
@@ -114,7 +116,7 @@ static int32_t uart_echo_worker(void* context) {
                 uint8_t data[64];
                 length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
                 if(length > 0 && app->initialized) {
-                    furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
+                    furi_hal_serial_tx(app->serial_handle, data, length);
                     with_view_model(
                         app->view,
                         UartDumpModel * model,
@@ -176,9 +178,10 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_thread_start(app->worker_thread);
 
     // Enable uart listener
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, 230400);
+    furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false);
 
     furi_hal_power_disable_external_3_3v();
     furi_hal_power_disable_otg();
@@ -187,7 +190,7 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_hal_power_enable_otg();
     for(int i = 0; i < 2; i++) {
         furi_delay_ms(500);
-        furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'m'}, 1);
+        furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'m'}, 1);
     }
     furi_delay_ms(1);
     app->initialized = true;
@@ -197,7 +200,8 @@ static UartEchoApp* uart_echo_app_alloc() {
 static void uart_echo_app_free(UartEchoApp* app) {
     furi_assert(app);
 
-    furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
     furi_thread_join(app->worker_thread);

+ 3 - 2
mayhem_motion/uart_echo.h

@@ -4,8 +4,8 @@
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
 #include <gui/elements.h>
-#include <furi_hal_uart.h>
-#include <furi_hal_console.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/view_dispatcher.h>
 #include <gui/modules/dialog_ex.h>
 
@@ -38,6 +38,7 @@ typedef struct {
     View* view;
     FuriThread* worker_thread;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
     bool initialized;
 } UartEchoApp;
 

+ 12 - 8
mayhem_nannycam/uart_echo.c

@@ -40,11 +40,13 @@ static uint32_t uart_echo_exit(void* context) {
     return VIEW_NONE;
 }
 
-static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
     UartEchoApp* app = context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
     }
@@ -108,7 +110,7 @@ static int32_t uart_echo_worker(void* context) {
                 uint8_t data[64];
                 length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
                 if(length > 0 && app->initialized) {
-                    furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
+                    furi_hal_serial_tx(app->serial_handle, data, length);
                     with_view_model(
                         app->view,
                         UartDumpModel * model,
@@ -170,9 +172,10 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_thread_start(app->worker_thread);
 
     // Enable uart listener
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, 230400);
+    furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false);
 
     furi_hal_power_disable_external_3_3v();
     furi_hal_power_disable_otg();
@@ -181,7 +184,7 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_hal_power_enable_otg();
     for(int i = 0; i < 2; i++) {
         furi_delay_ms(500);
-        furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'n'}, 1);
+        furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'n'}, 1);
     }
     furi_delay_ms(1);
     app->initialized = true;
@@ -191,7 +194,8 @@ static UartEchoApp* uart_echo_app_alloc() {
 static void uart_echo_app_free(UartEchoApp* app) {
     furi_assert(app);
 
-    furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
     furi_thread_join(app->worker_thread);

+ 3 - 2
mayhem_nannycam/uart_echo.h

@@ -4,8 +4,8 @@
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
 #include <gui/elements.h>
-#include <furi_hal_uart.h>
-#include <furi_hal_console.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/view_dispatcher.h>
 #include <gui/modules/dialog_ex.h>
 
@@ -21,6 +21,7 @@ typedef struct {
     View* view;
     FuriThread* worker_thread;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
     bool initialized;
 } UartEchoApp;
 

+ 12 - 8
mayhem_qrcode/uart_echo.c

@@ -40,11 +40,13 @@ static uint32_t uart_echo_exit(void* context) {
     return VIEW_NONE;
 }
 
-static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
     UartEchoApp* app = context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
     }
@@ -108,7 +110,7 @@ static int32_t uart_echo_worker(void* context) {
                 uint8_t data[64];
                 length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
                 if(length > 0 && app->initialized) {
-                    furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
+                    furi_hal_serial_tx(app->serial_handle, data, length);
                     with_view_model(
                         app->view,
                         UartDumpModel * model,
@@ -170,9 +172,10 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_thread_start(app->worker_thread);
 
     // Enable uart listener
-    furi_hal_console_disable();
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, 230400);
+    furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, false);
 
     furi_hal_power_disable_external_3_3v();
     furi_hal_power_disable_otg();
@@ -181,7 +184,7 @@ static UartEchoApp* uart_echo_app_alloc() {
     furi_hal_power_enable_otg();
     for(int i = 0; i < 2; i++) {
         furi_delay_ms(500);
-        furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'q'}, 1);
+        furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'q'}, 1);
     }
     furi_delay_ms(1);
     app->initialized = true;
@@ -191,7 +194,8 @@ static UartEchoApp* uart_echo_app_alloc() {
 static void uart_echo_app_free(UartEchoApp* app) {
     furi_assert(app);
 
-    furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
     furi_thread_join(app->worker_thread);

+ 3 - 2
mayhem_qrcode/uart_echo.h

@@ -4,8 +4,8 @@
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
 #include <gui/elements.h>
-#include <furi_hal_uart.h>
-#include <furi_hal_console.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/view_dispatcher.h>
 #include <gui/modules/dialog_ex.h>
 
@@ -21,6 +21,7 @@ typedef struct {
     View* view;
     FuriThread* worker_thread;
     FuriStreamBuffer* rx_stream;
+    FuriHalSerialHandle* serial_handle;
     bool initialized;
 } UartEchoApp;
 

+ 6 - 6
nrf24batch/nrf24batch.c

@@ -1539,12 +1539,12 @@ int32_t nrf24batch_app(void* p) {
         FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
         furi_mutex_acquire(APP->plugin_state->mutex, FuriWaitForever);
 
-        static FuriLogLevel FuriLogLevel = FuriLogLevelDefault;
-        if(furi_log_get_level() != FuriLogLevel) {
-            FuriLogLevel = furi_log_get_level();
-            if(FuriLogLevel == FuriLogLevelDebug)
-                furi_hal_uart_set_br(FuriHalUartIdUSART1, 1843200);
-        }
+        // static FuriLogLevel FuriLogLevel = FuriLogLevelDefault;
+        // if(furi_log_get_level() != FuriLogLevel) {
+        //     FuriLogLevel = furi_log_get_level();
+        //     if(FuriLogLevel == FuriLogLevelDebug)
+        //         furi_hal_uart_set_br(FuriHalUartIdUSART1, 1843200);
+        // }
         if(what_doing == 2 && rw_type == rwt_read_cmd && ReadRepeat &&
            furi_get_tick() - NRF_time > (uint32_t)(ReadCmdRepeatPeriod * 1000)) {
             ERR = 0;

+ 6 - 6
sentry_safe/sentry_safe.c

@@ -59,17 +59,17 @@ void send_request(int command, int a, int b, int c, int d, int e) {
     furi_delay_ms(3.4);
     furi_hal_gpio_write(&gpio_ext_pc1, true);
 
-    furi_hal_uart_init(FuriHalUartIdLPUART1, 4800);
-    //furi_hal_uart_set_br(FuriHalUartIdLPUART1, 4800);
-    //furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, usb_uart_on_irq_cb, usb_uart);
+    FuriHalSerialHandle* serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdLpuart);
+    furi_check(serial_handle);
+    furi_hal_serial_init(serial_handle, 4800);
 
     uint8_t data[8] = {0x0, command, a, b, c, d, e, checksum};
-    furi_hal_uart_tx(FuriHalUartIdLPUART1, data, 8);
+    furi_hal_serial_tx(serial_handle, data, 8);
 
     furi_delay_ms(100);
 
-    furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, NULL, NULL);
-    furi_hal_uart_deinit(FuriHalUartIdLPUART1);
+    furi_hal_serial_deinit(serial_handle);
+    furi_hal_serial_control_release(serial_handle);
 }
 
 void reset_code(int a, int b, int c, int d, int e) {

+ 10 - 8
uart_terminal/scenes/uart_terminal_scene_console_output.c

@@ -86,8 +86,6 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
     uart_terminal_uart_set_handle_rx_data_cb(
         app->uart, uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
 
-    uint8_t uart_ch = app->uart_ch;
-
     if(app->hex_mode) {
         // Send binary packet
         if(app->selected_tx_string) {
@@ -98,7 +96,7 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
                 byte |= (hex_char_to_byte(*str) << ((1 - digit_num) * 4));
 
                 if(++digit_num == 2) {
-                    uart_terminal_uart_tx(uart_ch, &byte, 1);
+                    uart_terminal_uart_tx(app->uart, &byte, 1);
                     digit_num = 0;
                     byte = 0;
                 }
@@ -106,7 +104,7 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
             }
 
             if(digit_num) {
-                uart_terminal_uart_tx(uart_ch, &byte, 1);
+                uart_terminal_uart_tx(app->uart, &byte, 1);
             }
         }
     } else {
@@ -114,12 +112,16 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
         if(app->is_command && app->selected_tx_string) {
             if(app->TERMINAL_MODE == 1) {
                 uart_terminal_uart_tx(
-                    uart_ch, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-                uart_terminal_uart_tx(uart_ch, (uint8_t*)("\r\n"), 2);
+                    app->uart,
+                    (uint8_t*)(app->selected_tx_string),
+                    strlen(app->selected_tx_string));
+                uart_terminal_uart_tx(app->uart, (uint8_t*)("\r\n"), 2);
             } else {
                 uart_terminal_uart_tx(
-                    uart_ch, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-                uart_terminal_uart_tx(uart_ch, (uint8_t*)("\n"), 1);
+                    app->uart,
+                    (uint8_t*)(app->selected_tx_string),
+                    strlen(app->selected_tx_string));
+                uart_terminal_uart_tx(app->uart, (uint8_t*)("\n"), 1);
             }
         }
     }

+ 15 - 17
uart_terminal/uart_terminal_uart.c

@@ -7,6 +7,7 @@ struct UART_TerminalUart {
     FuriStreamBuffer* rx_stream;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef enum {
@@ -23,10 +24,14 @@ void uart_terminal_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void uart_terminal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void uart_terminal_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     UART_TerminalUart* uart = (UART_TerminalUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
     }
@@ -53,8 +58,8 @@ static int32_t uart_worker(void* context) {
     return 0;
 }
 
-void uart_terminal_uart_tx(uint8_t uart_ch, uint8_t* data, size_t len) {
-    furi_hal_uart_tx(uart_ch, data, len);
+void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
 UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) {
@@ -74,14 +79,11 @@ UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) {
         app->BAUDRATE = 115200;
     }
 
-    if(app->uart_ch == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-        furi_hal_uart_set_br(app->uart_ch, app->BAUDRATE);
-    } else if(app->uart_ch == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(app->uart_ch, app->BAUDRATE);
-    }
+    uart->serial_handle = furi_hal_serial_control_acquire(app->uart_ch);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, app->BAUDRATE);
 
-    furi_hal_uart_set_irq_cb(app->uart_ch, uart_terminal_uart_on_irq_cb, uart);
+    furi_hal_serial_async_rx_start(uart->serial_handle, uart_terminal_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -93,12 +95,8 @@ void uart_terminal_uart_free(UART_TerminalUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    furi_hal_uart_set_irq_cb(uart->app->uart_ch, NULL, NULL);
-
-    if(uart->app->uart_ch == FuriHalUartIdUSART1)
-        furi_hal_console_enable();
-    else
-        furi_hal_uart_deinit(uart->app->uart_ch);
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 1
uart_terminal/uart_terminal_uart.h

@@ -9,6 +9,6 @@ typedef struct UART_TerminalUart UART_TerminalUart;
 void uart_terminal_uart_set_handle_rx_data_cb(
     UART_TerminalUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void uart_terminal_uart_tx(uint8_t uart_ch, uint8_t* data, size_t len);
+void uart_terminal_uart_tx(UART_TerminalUart* uart, uint8_t* data, size_t len);
 UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app);
 void uart_terminal_uart_free(UART_TerminalUart* uart);

+ 0 - 1
uhf_rfid/uhf_app.c

@@ -201,7 +201,6 @@ int32_t uhf_app_main(void* ctx) {
     furi_hal_power_enable_otg();
     // init pin a2
     // furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUDRATE);
     scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify);
     view_dispatcher_run(uhf_app->view_dispatcher);
 

+ 21 - 13
uhf_rfid/uhf_module.c

@@ -6,19 +6,22 @@
 
 volatile uint16_t tick = 0;
 
-void rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
+void rx_callback(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* ctx) {
     UNUSED(event);
     Buffer* buffer = ctx;
     if(buffer->closed) return; // buffer closed
-    buffer_append_single(buffer, data); // append data
-    if(data == FRAME_END) buffer_close(buffer); // end of frame
-    tick = WAIT_TICK; // reset tick
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
+        buffer_append_single(buffer, data); // append data
+        if(data == FRAME_END) buffer_close(buffer); // end of frame
+        tick = WAIT_TICK; // reset tick
+    }
 }
 
 static M100ResponseType setup_and_send_rx(M100Module* module, uint8_t* cmd, size_t cmd_length) {
     buffer_reset(module->buf);
     tick = WAIT_TICK;
-    furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, cmd_length);
+    furi_hal_serial_tx(module->serial_handle, cmd, cmd_length);
     while(--tick) {
         furi_delay_us(5);
     }
@@ -53,11 +56,16 @@ M100Module* m100_module_alloc() {
     module->baudrate = DEFAULT_BAUDRATE;
     module->transmitting_power = DEFAULT_TRANSMITTING_POWER;
     module->region = DEFAULT_WORKING_REGION;
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
+    module->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    furi_check(module->serial_handle);
+    furi_hal_serial_init(module->serial_handle, module->baudrate);
+    furi_hal_serial_async_rx_start(module->serial_handle, rx_callback, module->buf, false);
     return module;
 }
 
 void m100_module_free(M100Module* module) {
+    furi_hal_serial_deinit(module->serial_handle);
+    furi_hal_serial_control_release(module->serial_handle);
     m100_module_info_free(module->info);
     buffer_free(module->buf);
     free(module);
@@ -195,9 +203,9 @@ M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
 
 UHFTag* m100_get_select_param(M100Module* module) {
     buffer_reset(module->buf);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, rx_callback, module->buf);
-    furi_hal_uart_tx(
-        FuriHalUartIdUSART1,
+    // furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, rx_callback, module->buf);
+    furi_hal_serial_tx(
+        module->serial_handle,
         (uint8_t*)&CMD_GET_SELECT_PARAMETER.cmd,
         CMD_GET_SELECT_PARAMETER.length);
     furi_delay_ms(DELAY_MS);
@@ -318,8 +326,8 @@ M100ResponseType m100_write_label_data_storage(
     cmd[cmd_length - 2] = checksum(cmd + 1, cmd_length - 3);
     cmd[cmd_length - 1] = FRAME_END;
     // send cmd
-    // furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
-    // furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, cmd_length);
+    // furi_hal_serial_async_rx_start(module->serial_handle, rx_callback, module->buf, false);
+    // furi_hal_serial_tx(module->serial_handle, cmd, cmd_length);
     // unsigned int delay = DELAY_MS / 2;
     // unsigned int timeout = 15;
     // while(!buffer_get_size(module->buf)) {
@@ -343,8 +351,8 @@ void m100_set_baudrate(M100Module* module, uint32_t baudrate) {
     cmd[6] = 0xFF & br_mod; // pow LSB
     cmd[5] = 0xFF & (br_mod >> 8); // pow MSB
     cmd[length - 2] = checksum(cmd + 1, length - 3);
-    furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, length);
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
+    furi_hal_serial_tx(module->serial_handle, cmd, length);
+    furi_hal_serial_set_br(module->serial_handle, baudrate);
     module->baudrate = baudrate;
 }
 

+ 1 - 0
uhf_rfid/uhf_module.h

@@ -39,6 +39,7 @@ typedef struct {
     uint16_t transmitting_power;
     bool freq_hopping;
     Buffer* buf;
+    FuriHalSerialHandle* serial_handle;
 } M100Module;
 
 M100ModuleInfo* m100_module_info_alloc();

+ 2 - 0
wardriver/wardriver.h

@@ -67,10 +67,12 @@ typedef struct {
     FuriThread* thread_esp;
     FuriStreamBuffer* rx_stream_esp;
     uint8_t rx_buf_esp[2048];
+    FuriHalSerialHandle* serial_handle_esp;
 
     FuriThread* thread_gps;
     FuriStreamBuffer* rx_stream_gps;
     uint8_t rx_buf_gps[2048];
+    FuriHalSerialHandle* serial_handle_gps;
 
     uint16_t access_points_count;
     AccessPoint access_points[MAX_ACCESS_POINTS];

+ 19 - 29
wardriver/wardriver_uart.c

@@ -198,10 +198,11 @@ static void uart_parse_esp(void* context, char* line) {
     }
 }
 
-static void uart_cb_esp(UartIrqEvent ev, uint8_t data, void* context) {
+static void uart_cb_esp(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     Context* ctx = (Context*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(ctx->rx_stream_esp, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(ctx->thread_esp), WorkerEvtRxDone);
     }
@@ -321,10 +322,11 @@ static void uart_parse_gps(Context* ctx, char* line) {
     }
 }
 
-static void uart_cb_gps(UartIrqEvent ev, uint8_t data, void* context) {
+static void uart_cb_gps(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     Context* ctx = (Context*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(ctx->rx_stream_gps, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(ctx->thread_gps), WorkerEvtRxDone);
     }
@@ -415,13 +417,10 @@ void wardriver_uart_init(Context* ctx) {
 
     furi_thread_start(ctx->thread_esp);
 
-    if(UART_CH_ESP == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH_ESP == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH_ESP, 115200);
-    }
-    furi_hal_uart_set_br(UART_CH_ESP, 115200);
-    furi_hal_uart_set_irq_cb(UART_CH_ESP, uart_cb_esp, ctx);
+    ctx->serial_handle_esp = furi_hal_serial_control_acquire(UART_CH_ESP);
+    furi_check(ctx->serial_handle_esp);
+    furi_hal_serial_init(ctx->serial_handle_esp, 115200);
+    furi_hal_serial_async_rx_start(ctx->serial_handle_esp, uart_cb_esp, ctx, false);
 
     if(UART_CH_ESP != UART_CH_GPS) {
         ctx->rx_stream_gps = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
@@ -434,13 +433,10 @@ void wardriver_uart_init(Context* ctx) {
 
         furi_thread_start(ctx->thread_gps);
 
-        if(UART_CH_GPS == FuriHalUartIdUSART1) {
-            furi_hal_console_disable();
-        } else if(UART_CH_GPS == FuriHalUartIdLPUART1) {
-            furi_hal_uart_init(UART_CH_GPS, 9600);
-        }
-        furi_hal_uart_set_br(UART_CH_GPS, 9600);
-        furi_hal_uart_set_irq_cb(UART_CH_GPS, uart_cb_gps, ctx);
+        ctx->serial_handle_gps = furi_hal_serial_control_acquire(UART_CH_GPS);
+        furi_check(ctx->serial_handle_gps);
+        furi_hal_serial_init(ctx->serial_handle_gps, 9600);
+        furi_hal_serial_async_rx_start(ctx->serial_handle_gps, uart_cb_gps, ctx, false);
     }
 
     return;
@@ -450,27 +446,21 @@ 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);
     }
 
-    if(UART_CH_ESP == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH_ESP);
-    } else if(UART_CH_ESP == FuriHalUartIdUSART1) {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(ctx->serial_handle_esp);
+    furi_hal_serial_control_release(ctx->serial_handle_esp);
 
-    if(UART_CH_GPS == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH_GPS);
-    } else if(UART_CH_GPS == FuriHalUartIdUSART1) {
-        furi_hal_console_enable();
+    if(UART_CH_ESP != UART_CH_GPS) {
+        furi_hal_serial_deinit(ctx->serial_handle_gps);
+        furi_hal_serial_control_release(ctx->serial_handle_gps);
     }
 
     return;

+ 2 - 4
wardriver/wardriver_uart.h

@@ -1,10 +1,8 @@
 #include "wardriver.h"
 
-#define UART_CH_ESP \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH_ESP (xtreme_settings.uart_esp_channel)
 
-#define UART_CH_GPS \
-    (xtreme_settings.uart_nmea_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH_GPS (xtreme_settings.uart_nmea_channel)
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 

+ 3 - 3
wifi_deauther/scenes/wifi_deauther_scene_console_output.c

@@ -57,8 +57,8 @@ void wifi_deauther_scene_console_output_on_enter(void* context) {
     // Send command with newline '\n'
     if(app->is_command && app->selected_tx_string) {
         wifi_deauther_uart_tx(
-            (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
-        wifi_deauther_uart_tx((uint8_t*)("\n"), 1);
+            app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+        wifi_deauther_uart_tx(app->uart, (uint8_t*)("\n"), 1);
     }
 }
 
@@ -85,6 +85,6 @@ void wifi_deauther_scene_console_output_on_exit(void* context) {
 
     // Automatically stop the scan when exiting view
     if(app->is_command) {
-        wifi_deauther_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
+        wifi_deauther_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n"));
     }
 }

+ 1 - 2
wifi_deauther/wifi_deauther_app_i.h

@@ -14,8 +14,7 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 
 #define NUM_MENU_ITEMS (11)
 

+ 15 - 19
wifi_deauther/wifi_deauther_uart.c

@@ -8,11 +8,11 @@
 
 struct WifideautherUart {
     WifideautherApp* app;
-    FuriHalUartId channel;
     FuriThread* rx_thread;
     FuriStreamBuffer* rx_stream;
     uint8_t rx_buf[RX_BUF_SIZE + 1];
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    FuriHalSerialHandle* serial_handle;
 };
 
 typedef enum {
@@ -29,10 +29,14 @@ void wifi_deauther_uart_set_handle_rx_data_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
 
-void wifi_deauther_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void wifi_deauther_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     WifideautherUart* uart = (WifideautherUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         furi_stream_buffer_send(uart->rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone);
     }
@@ -54,14 +58,13 @@ static int32_t uart_worker(void* context) {
         }
     }
 
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
     furi_stream_buffer_free(uart->rx_stream);
 
     return 0;
 }
 
-void wifi_deauther_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void wifi_deauther_uart_tx(WifideautherUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
 WifideautherUart* wifi_deauther_uart_init(WifideautherApp* app) {
@@ -77,14 +80,10 @@ WifideautherUart* wifi_deauther_uart_init(WifideautherApp* app) {
 
     furi_thread_start(uart->rx_thread);
 
-    if(UART_CH == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, BAUDRATE);
-    }
-
-    furi_hal_uart_set_br(UART_CH, BAUDRATE);
-    furi_hal_uart_set_irq_cb(UART_CH, wifi_deauther_uart_on_irq_cb, uart);
+    uart->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, wifi_deauther_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -96,11 +95,8 @@ void wifi_deauther_uart_free(WifideautherUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 1
wifi_deauther/wifi_deauther_uart.h

@@ -9,6 +9,6 @@ typedef struct WifideautherUart WifideautherUart;
 void wifi_deauther_uart_set_handle_rx_data_cb(
     WifideautherUart* uart,
     void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
-void wifi_deauther_uart_tx(uint8_t* data, size_t len);
+void wifi_deauther_uart_tx(WifideautherUart* uart, uint8_t* data, size_t len);
 WifideautherUart* wifi_deauther_uart_init(WifideautherApp* app);
 void wifi_deauther_uart_free(WifideautherUart* uart);

+ 11 - 9
wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c

@@ -157,15 +157,15 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
         // Send command with newline '\n'
         if(app->selected_tx_string) {
             wifi_marauder_uart_tx(
-                (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+                app->uart, (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
             if(app->is_writing_pcap) {
-                wifi_marauder_uart_tx((uint8_t*)(" -serial\n"), strlen(" -serial\n"));
+                wifi_marauder_uart_tx(app->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n"));
             } else {
-                wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+                wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
             }
             if(send_html && the_html) {
-                wifi_marauder_uart_tx(the_html, html_size);
-                wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+                wifi_marauder_uart_tx(app->uart, the_html, html_size);
+                wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
                 free(the_html);
                 send_html = false;
             }
@@ -173,7 +173,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
 
         // Run the script if the file with the script has been opened
         if(app->script != NULL) {
-            app->script_worker = wifi_marauder_script_worker_alloc();
+            app->script_worker = wifi_marauder_script_worker_alloc(app->uart);
             wifi_marauder_script_worker_start(app->script_worker, app->script);
         }
     }
@@ -199,7 +199,7 @@ void wifi_marauder_scene_console_output_on_exit(void* context) {
 
     // Automatically stop the scan when exiting view
     if(app->is_command) {
-        wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
+        wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n"));
         furi_delay_ms(50);
     }
 
@@ -207,8 +207,10 @@ void wifi_marauder_scene_console_output_on_exit(void* context) {
     wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL);
     wifi_marauder_uart_set_handle_rx_pcap_cb(app->uart, NULL);
 
-    wifi_marauder_script_worker_free(app->script_worker);
-    app->script_worker = NULL;
+    if(app->script_worker) {
+        wifi_marauder_script_worker_free(app->script_worker);
+        app->script_worker = NULL;
+    }
 
     app->is_writing_pcap = false;
     if(app->capture_file && storage_file_is_open(app->capture_file)) {

+ 52 - 47
wifi_marauder_companion/script/wifi_marauder_script_executor.c

@@ -5,20 +5,20 @@ void _wifi_marauder_script_delay(WifiMarauderScriptWorker* worker, uint32_t dela
     for(uint32_t i = 0; i < delay_secs && worker->is_running; i++) furi_delay_ms(1000);
 }
 
-void _send_stop() {
+void _send_stop(WifiMarauderScriptWorker* worker) {
     const char stop_command[] = "stopscan\n";
-    wifi_marauder_uart_tx((uint8_t*)(stop_command), strlen(stop_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(stop_command), strlen(stop_command));
 }
 
-void _send_line_break() {
-    wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
+void _send_line_break(WifiMarauderScriptWorker* worker) {
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1);
 }
 
-void _send_channel_select(int channel) {
+void _send_channel_select(WifiMarauderScriptWorker* worker, int channel) {
     char command[30];
-    _send_line_break();
+    _send_line_break(worker);
     snprintf(command, sizeof(command), "channel -s %d\n", channel);
-    wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
 }
 
 void _wifi_marauder_script_execute_scan(
@@ -27,7 +27,7 @@ void _wifi_marauder_script_execute_scan(
     char command[15];
     // Set channel
     if(stage->channel > 0) {
-        _send_channel_select(stage->channel);
+        _send_channel_select(worker, stage->channel);
     }
     // Start scan
     if(stage->type == WifiMarauderScriptScanTypeAp) {
@@ -35,12 +35,14 @@ void _wifi_marauder_script_execute_scan(
     } else {
         snprintf(command, sizeof(command), "scansta\n");
     }
-    wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
-void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage) {
+void _wifi_marauder_script_execute_select(
+    WifiMarauderScriptStageSelect* stage,
+    WifiMarauderScriptWorker* worker) {
     const char* select_type = NULL;
     switch(stage->type) {
     case WifiMarauderScriptSelectTypeAp:
@@ -79,61 +81,61 @@ void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage)
             command, sizeof(command), "select %s -f \"%s\"\n", select_type, stage->filter);
     }
 
-    wifi_marauder_uart_tx((uint8_t*)command, command_length);
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, command_length);
 }
 
 void _wifi_marauder_script_execute_deauth(
     WifiMarauderScriptStageDeauth* stage,
     WifiMarauderScriptWorker* worker) {
     const char attack_command[] = "attack -t deauth\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_probe(
     WifiMarauderScriptStageProbe* stage,
     WifiMarauderScriptWorker* worker) {
     const char attack_command[] = "attack -t probe\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_raw(
     WifiMarauderScriptStageSniffRaw* stage,
     WifiMarauderScriptWorker* worker) {
     const char sniff_command[] = "sniffraw -serial\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_beacon(
     WifiMarauderScriptStageSniffBeacon* stage,
     WifiMarauderScriptWorker* worker) {
     const char sniff_command[] = "sniffbeacon -serial\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_deauth(
     WifiMarauderScriptStageSniffDeauth* stage,
     WifiMarauderScriptWorker* worker) {
     const char sniff_command[] = "sniffdeauth -serial\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_esp(
     WifiMarauderScriptStageSniffEsp* stage,
     WifiMarauderScriptWorker* worker) {
     const char sniff_command[] = "sniffesp -serial\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_sniff_pmkid(
@@ -151,9 +153,9 @@ void _wifi_marauder_script_execute_sniff_pmkid(
             }
 
             len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n");
-            wifi_marauder_uart_tx((uint8_t*)attack_command, len);
+            wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len);
             _wifi_marauder_script_delay(worker, stage->timeout);
-            _send_stop();
+            _send_stop(worker);
         }
     } else {
         char attack_command[50] = "sniffpmkid";
@@ -168,9 +170,9 @@ void _wifi_marauder_script_execute_sniff_pmkid(
             len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d");
         }
         len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n");
-        wifi_marauder_uart_tx((uint8_t*)attack_command, len);
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len);
         _wifi_marauder_script_delay(worker, stage->timeout);
-        _send_stop();
+        _send_stop(worker);
     }
 }
 
@@ -178,16 +180,16 @@ void _wifi_marauder_script_execute_sniff_pwn(
     WifiMarauderScriptStageSniffPwn* stage,
     WifiMarauderScriptWorker* worker) {
     const char sniff_command[] = "sniffpwn -serial\n";
-    wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_beacon_list(
     WifiMarauderScriptStageBeaconList* stage,
     WifiMarauderScriptWorker* worker) {
     const char clearlist_command[] = "clearlist -s\n";
-    wifi_marauder_uart_tx((uint8_t*)(clearlist_command), strlen(clearlist_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(clearlist_command), strlen(clearlist_command));
 
     char command[100];
     char* ssid;
@@ -195,8 +197,8 @@ void _wifi_marauder_script_execute_beacon_list(
     for(int i = 0; i < stage->ssid_count; i++) {
         ssid = stage->ssids[i];
         snprintf(command, sizeof(command), "ssid -a -n \"%s\"", ssid);
-        wifi_marauder_uart_tx((uint8_t*)(command), strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command));
+        _send_line_break(worker);
     }
     if(stage->random_ssids > 0) {
         char add_random_command[50];
@@ -205,27 +207,30 @@ void _wifi_marauder_script_execute_beacon_list(
             sizeof(add_random_command),
             "ssid -a -r -g %d\n",
             stage->random_ssids);
-        wifi_marauder_uart_tx((uint8_t*)add_random_command, strlen(add_random_command));
+        wifi_marauder_uart_tx(
+            worker->uart, (uint8_t*)add_random_command, strlen(add_random_command));
     }
     const char attack_command[] = "attack -t beacon -l\n";
-    wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
 void _wifi_marauder_script_execute_beacon_ap(
     WifiMarauderScriptStageBeaconAp* stage,
     WifiMarauderScriptWorker* worker) {
     const char command[] = "attack -t beacon -a\n";
-    wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
+    wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
     _wifi_marauder_script_delay(worker, stage->timeout);
-    _send_stop();
+    _send_stop(worker);
 }
 
-void _wifi_marauder_script_execute_exec(WifiMarauderScriptStageExec* stage) {
+void _wifi_marauder_script_execute_exec(
+    WifiMarauderScriptStageExec* stage,
+    WifiMarauderScriptWorker* worker) {
     if(stage->command != NULL) {
-        wifi_marauder_uart_tx((uint8_t*)stage->command, strlen(stage->command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)stage->command, strlen(stage->command));
+        _send_line_break(worker);
     }
 }
 
@@ -248,8 +253,8 @@ void wifi_marauder_script_execute_start(void* context) {
             sizeof(command),
             "settings -s EnableLED %s",
             script->enable_led ? "enable" : "disable");
-        wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
+        _send_line_break(worker);
     }
 
     // Enables or disables PCAP saving according to script settings
@@ -259,8 +264,8 @@ void wifi_marauder_script_execute_start(void* context) {
             sizeof(command),
             "settings -s SavePCAP %s",
             script->save_pcap ? "enable" : "disable");
-        wifi_marauder_uart_tx((uint8_t*)command, strlen(command));
-        _send_line_break();
+        wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command));
+        _send_line_break(worker);
     }
 }
 
@@ -274,7 +279,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co
         _wifi_marauder_script_execute_scan((WifiMarauderScriptStageScan*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeSelect:
-        _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data);
+        _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeDeauth:
         _wifi_marauder_script_execute_deauth((WifiMarauderScriptStageDeauth*)stage_data, worker);
@@ -315,7 +320,7 @@ void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* co
             (WifiMarauderScriptStageBeaconAp*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeExec:
-        _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data);
+        _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data, worker);
         break;
     case WifiMarauderScriptStageTypeDelay:
         _wifi_marauder_script_execute_delay((WifiMarauderScriptStageDelay*)stage_data, worker);

+ 2 - 1
wifi_marauder_companion/script/wifi_marauder_script_worker.c

@@ -1,7 +1,7 @@
 #include "../wifi_marauder_app_i.h"
 #include "wifi_marauder_script_worker.h"
 
-WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() {
+WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(WifiMarauderUart* uart) {
     WifiMarauderScriptWorker* worker = malloc(sizeof(WifiMarauderScriptWorker));
     if(worker == NULL) {
         return NULL;
@@ -9,6 +9,7 @@ WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() {
     worker->callback_start = NULL;
     worker->callback_stage = NULL;
     worker->worker_thread = NULL;
+    worker->uart = uart;
     worker->is_running = false;
     return worker;
 }

+ 1 - 0
wifi_marauder_companion/script/wifi_marauder_script_worker.h

@@ -11,6 +11,7 @@ typedef enum {
 typedef struct WifiMarauderScriptWorker {
     WifiMarauderScript* script;
     FuriThread* worker_thread;
+    WifiMarauderUart* uart;
     void (*callback_start)(void*);
     void (*callback_stage)(WifiMarauderScriptStage*, void*);
     void* context;

+ 20 - 23
wifi_marauder_companion/wifi_marauder_uart.c

@@ -3,16 +3,15 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)
 #define BAUDRATE (115200)
 
 struct WifiMarauderUart {
     WifiMarauderApp* app;
-    FuriHalUartId channel;
     FuriThread* rx_thread;
     FuriStreamBuffer* rx_stream;
     FuriStreamBuffer* pcap_stream;
+    FuriHalSerialHandle* serial_handle;
     bool pcap;
     uint8_t mark_test_buf[11];
     uint8_t mark_test_idx;
@@ -43,10 +42,14 @@ void wifi_marauder_uart_set_handle_rx_pcap_cb(
 
 #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone | WorkerEvtPcapDone)
 
-void wifi_marauder_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+void wifi_marauder_uart_on_irq_cb(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context) {
     WifiMarauderUart* uart = (WifiMarauderUart*)context;
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         const char* mark_begin = "[BUF/BEGIN]";
         const char* mark_close = "[BUF/CLOSE]";
         if(uart->mark_test_idx != 0) {
@@ -131,16 +134,17 @@ static int32_t uart_worker(void* context) {
     return 0;
 }
 
-void wifi_marauder_uart_tx(uint8_t* data, size_t len) {
-    furi_hal_uart_tx(UART_CH, data, len);
+void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len) {
+    furi_hal_serial_tx(uart->serial_handle, data, len);
 }
 
-WifiMarauderUart*
-    wifi_marauder_uart_init(WifiMarauderApp* app, FuriHalUartId channel, const char* thread_name) {
+WifiMarauderUart* wifi_marauder_uart_init(
+    WifiMarauderApp* app,
+    FuriHalSerialId channel,
+    const char* thread_name) {
     WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart));
 
     uart->app = app;
-    uart->channel = channel;
     uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     uart->pcap_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     uart->rx_thread = furi_thread_alloc();
@@ -149,13 +153,10 @@ WifiMarauderUart*
     furi_thread_set_context(uart->rx_thread, uart);
     furi_thread_set_callback(uart->rx_thread, uart_worker);
     furi_thread_start(uart->rx_thread);
-    if(channel == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(channel, BAUDRATE);
-    }
-    furi_hal_uart_set_br(channel, BAUDRATE);
-    furi_hal_uart_set_irq_cb(channel, wifi_marauder_uart_on_irq_cb, uart);
+    uart->serial_handle = furi_hal_serial_control_acquire(channel);
+    furi_check(uart->serial_handle);
+    furi_hal_serial_init(uart->serial_handle, BAUDRATE);
+    furi_hal_serial_async_rx_start(uart->serial_handle, wifi_marauder_uart_on_irq_cb, uart, false);
 
     return uart;
 }
@@ -171,12 +172,8 @@ void wifi_marauder_uart_free(WifiMarauderUart* uart) {
     furi_thread_join(uart->rx_thread);
     furi_thread_free(uart->rx_thread);
 
-    furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL);
-    if(uart->channel == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(uart->channel);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(uart->serial_handle);
+    furi_hal_serial_control_release(uart->serial_handle);
 
     free(uart);
 }

+ 1 - 1
wifi_marauder_companion/wifi_marauder_uart.h

@@ -12,6 +12,6 @@ void wifi_marauder_uart_set_handle_rx_data_cb(
 void wifi_marauder_uart_set_handle_rx_pcap_cb(
     WifiMarauderUart* uart,
     void (*handle_rx_pcap_cb)(uint8_t* buf, size_t len, void* context));
-void wifi_marauder_uart_tx(uint8_t* data, size_t len);
+void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len);
 WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app);
 void wifi_marauder_uart_free(WifiMarauderUart* uart);

+ 1 - 2
wifi_scanner/FlipperZeroWiFiModuleDefines.h

@@ -18,5 +18,4 @@
 
 #include <xtreme/xtreme.h>
 
-#define UART_CH \
-    (xtreme_settings.uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : FuriHalUartIdLPUART1)
+#define UART_CH (xtreme_settings.uart_esp_channel)

+ 23 - 27
wifi_scanner/wifi_scanner.c

@@ -1,8 +1,8 @@
 #include <furi.h>
-#include <furi_hal_console.h>
 #include <furi_hal_gpio.h>
 #include <furi_hal_power.h>
-#include <furi_hal_uart.h>
+#include <furi_hal_serial_control.h>
+#include <furi_hal_serial.h>
 #include <gui/canvas_i.h>
 #include <gui/gui.h>
 #include <input/input.h>
@@ -84,6 +84,7 @@ typedef struct SWiFiScannerApp {
     FuriThread* m_worker_thread;
     NotificationApp* m_notification;
     FuriStreamBuffer* m_rx_stream;
+    FuriHalSerialHandle* serial_handle;
 
     bool m_wifiModuleInitialized;
     bool m_wifiModuleAttached;
@@ -641,14 +642,16 @@ static void wifi_module_input_callback(InputEvent* input_event, FuriMessageQueue
     furi_message_queue_put(event_queue, &event, FuriWaitForever);
 }
 
-static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+static void
+    uart_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
     furi_assert(context);
 
     SWiFiScannerApp* app = context;
 
     WIFI_APP_LOG_I("uart_echo_on_irq_cb");
 
-    if(ev == UartIrqEventRXNE) {
+    if(event == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
         WIFI_APP_LOG_I("ev == UartIrqEventRXNE");
         furi_stream_buffer_send(app->m_rx_stream, &data, 1, 0);
         furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventRx);
@@ -806,7 +809,7 @@ typedef enum ESerialCommand {
     ESerialCommand_Restart
 } ESerialCommand;
 
-void send_serial_command(ESerialCommand command) {
+void send_serial_command(SWiFiScannerApp* app, ESerialCommand command) {
     uint8_t data[1] = {0};
 
     switch(command) {
@@ -829,7 +832,7 @@ void send_serial_command(ESerialCommand command) {
         return;
     };
 
-    furi_hal_uart_tx(UART_CH, data, 1);
+    furi_hal_serial_tx(app->serial_handle, data, 1);
 }
 
 int32_t wifi_scanner_app(void* p) {
@@ -899,18 +902,14 @@ int32_t wifi_scanner_app(void* p) {
     WIFI_APP_LOG_I("UART thread allocated");
 
     // Enable uart listener
-    if(UART_CH == FuriHalUartIdUSART1) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, FLIPPERZERO_SERIAL_BAUD);
-    }
-
-    furi_hal_uart_set_br(UART_CH, FLIPPERZERO_SERIAL_BAUD);
-    furi_hal_uart_set_irq_cb(UART_CH, uart_on_irq_cb, app);
+    app->serial_handle = furi_hal_serial_control_acquire(UART_CH);
+    furi_check(app->serial_handle);
+    furi_hal_serial_init(app->serial_handle, FLIPPERZERO_SERIAL_BAUD);
+    furi_hal_serial_async_rx_start(app->serial_handle, uart_on_irq_cb, app, false);
     WIFI_APP_LOG_I("UART Listener created");
 
     // Because we assume that module was on before we launched the app. We need to ensure that module will be in initial state on app start
-    send_serial_command(ESerialCommand_Restart);
+    send_serial_command(app, ESerialCommand_Restart);
 
     SPluginEvent event;
     for(bool processing = true; processing;) {
@@ -944,20 +943,20 @@ int32_t wifi_scanner_app(void* p) {
                         case InputKeyLeft:
                             if(event.m_input.type == InputTypeShort) {
                                 WIFI_APP_LOG_I("Previous");
-                                send_serial_command(ESerialCommand_Previous);
+                                send_serial_command(app, ESerialCommand_Previous);
                             } else if(event.m_input.type == InputTypeRepeat) {
                                 WIFI_APP_LOG_I("Previous Repeat");
-                                send_serial_command(ESerialCommand_Previous);
+                                send_serial_command(app, ESerialCommand_Previous);
                             }
                             break;
                         case InputKeyDown:
                         case InputKeyRight:
                             if(event.m_input.type == InputTypeShort) {
                                 WIFI_APP_LOG_I("Next");
-                                send_serial_command(ESerialCommand_Next);
+                                send_serial_command(app, ESerialCommand_Next);
                             } else if(event.m_input.type == InputTypeRepeat) {
                                 WIFI_APP_LOG_I("Next Repeat");
-                                send_serial_command(ESerialCommand_Next);
+                                send_serial_command(app, ESerialCommand_Next);
                             }
                             break;
                         default:
@@ -970,18 +969,18 @@ int32_t wifi_scanner_app(void* p) {
                         if(event.m_input.type == InputTypeShort) {
                             if(app->m_context == ScanMode) {
                                 WIFI_APP_LOG_I("Monitor Mode");
-                                send_serial_command(ESerialCommand_MonitorMode);
+                                send_serial_command(app, ESerialCommand_MonitorMode);
                             }
                         } else if(event.m_input.type == InputTypeLong) {
                             WIFI_APP_LOG_I("Scan");
-                            send_serial_command(ESerialCommand_Scan);
+                            send_serial_command(app, ESerialCommand_Scan);
                         }
                         break;
                     case InputKeyBack:
                         if(event.m_input.type == InputTypeShort) {
                             switch(app->m_context) {
                             case MonitorMode:
-                                send_serial_command(ESerialCommand_Scan);
+                                send_serial_command(app, ESerialCommand_Scan);
                                 break;
                             case ScanMode:
                                 processing = false;
@@ -1031,11 +1030,8 @@ int32_t wifi_scanner_app(void* p) {
     // Reset GPIO pins to default state
     furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
 
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
+    furi_hal_serial_deinit(app->serial_handle);
+    furi_hal_serial_control_release(app->serial_handle);
 
     view_port_enabled_set(view_port, false);