Kaynağa Gözat

[FL-2256] USB Service (#998)

* usb service, removed power observer
* fix usb restart after disable
* remove usb service from apps
* Applcations: remove dead extern
* New thread naming scheme for drivers
* New thread symbol naming scheme for drivers

Co-authored-by: あく <alleteam@gmail.com>
Nikolay Minaylov 3 yıl önce
ebeveyn
işleme
242241987e

+ 0 - 5
applications/applications.c

@@ -11,7 +11,6 @@ extern int32_t gui_srv(void* p);
 extern int32_t input_srv(void* p);
 extern int32_t input_srv(void* p);
 extern int32_t loader_srv(void* p);
 extern int32_t loader_srv(void* p);
 extern int32_t notification_srv(void* p);
 extern int32_t notification_srv(void* p);
-extern int32_t power_observer_srv(void* p);
 extern int32_t power_srv(void* p);
 extern int32_t power_srv(void* p);
 extern int32_t storage_srv(void* p);
 extern int32_t storage_srv(void* p);
 extern int32_t desktop_srv(void* p);
 extern int32_t desktop_srv(void* p);
@@ -115,10 +114,6 @@ const FlipperApplication FLIPPER_SERVICES[] = {
     {.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL},
     {.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL},
 #endif
 #endif
 
 
-#ifdef SRV_POWER_OBSERVER
-    {.app = power_observer_srv, .name = "PowerAuditSrv", .stack_size = 1024, .icon = NULL},
-#endif
-
 #ifdef SRV_STORAGE
 #ifdef SRV_STORAGE
     {.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL},
     {.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL},
 #endif
 #endif

+ 0 - 8
applications/applications.mk

@@ -18,7 +18,6 @@ SRV_INPUT	= 1
 SRV_LOADER	= 1
 SRV_LOADER	= 1
 SRV_NOTIFICATION = 1
 SRV_NOTIFICATION = 1
 SRV_POWER	= 1
 SRV_POWER	= 1
-SRV_POWER_OBSERVER = 1
 SRV_RPC = 1
 SRV_RPC = 1
 SRV_STORAGE	= 1
 SRV_STORAGE	= 1
 
 
@@ -256,13 +255,6 @@ endif
 endif
 endif
 
 
 
 
-SRV_POWER_OBSERVER ?= 0
-ifeq ($(SRV_POWER_OBSERVER), 1)
-CFLAGS		+= -DSRV_POWER_OBSERVER
-SRV_POWER	= 1
-endif
-
-
 SRV_POWER ?= 0
 SRV_POWER ?= 0
 ifeq ($(SRV_POWER), 1)
 ifeq ($(SRV_POWER), 1)
 CFLAGS		+= -DSRV_POWER
 CFLAGS		+= -DSRV_POWER

+ 5 - 0
applications/power/power_service/power.c

@@ -196,6 +196,11 @@ int32_t power_srv(void* p) {
         // Update battery view port
         // Update battery view port
         if(need_refresh) view_port_update(power->battery_view_port);
         if(need_refresh) view_port_update(power->battery_view_port);
 
 
+        // Check OTG status and disable it in case of fault
+        if(furi_hal_power_is_otg_enabled()) {
+            furi_hal_power_check_otg_status();
+        }
+
         osDelay(1000);
         osDelay(1000);
     }
     }
 
 

+ 0 - 76
applications/power_observer/power_observer.c

@@ -1,76 +0,0 @@
-#include <furi.h>
-#include <furi_hal.h>
-#include <notification/notification_messages.h>
-
-typedef struct {
-    osThreadId_t thread;
-
-} PowerObserverSrv;
-
-const NotificationMessage message_green_110 = {
-    .type = NotificationMessageTypeLedGreen,
-    .data.led.value = 110,
-};
-
-static const NotificationSequence sequence_overconsumption = {
-    &message_green_110,
-    &message_red_255,
-    &message_delay_100,
-    NULL,
-};
-
-typedef enum {
-    EventReset = (1 << 0),
-    EventRequest = (1 << 1),
-} UsbEvent;
-
-static void usb_state_callback(FuriHalUsbStateEvent state, void* context) {
-    PowerObserverSrv* srv = (PowerObserverSrv*)(context);
-    if(state == FuriHalUsbStateEventReset) {
-        osThreadFlagsSet(srv->thread, EventReset);
-    } else if(state == FuriHalUsbStateEventDescriptorRequest) {
-        osThreadFlagsSet(srv->thread, EventRequest);
-    }
-}
-
-int32_t power_observer_srv(void* p) {
-    NotificationApp* notifications = furi_record_open("notification");
-    PowerObserverSrv* srv = furi_alloc(sizeof(PowerObserverSrv));
-    srv->thread = osThreadGetId();
-
-    const float overconsumption_limit = 0.03f;
-    bool usb_request_pending = false;
-    uint8_t usb_wait_time = 0;
-
-    furi_hal_usb_set_state_callback(usb_state_callback, srv);
-
-    while(true) {
-        uint32_t flags = osThreadFlagsWait(EventReset | EventRequest, osFlagsWaitAny, 500);
-        if((flags & osFlagsError) == 0) {
-            if(flags & EventReset) {
-                usb_request_pending = true;
-                usb_wait_time = 0;
-            }
-            if(flags & EventRequest) {
-                usb_request_pending = false;
-            }
-        } else if(usb_request_pending) {
-            usb_wait_time++;
-            if(usb_wait_time > 4) {
-                furi_hal_usb_reinit();
-                usb_request_pending = false;
-            }
-        }
-
-        float current = -furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
-        if(current > overconsumption_limit) {
-            notification_message_block(notifications, &sequence_overconsumption);
-        }
-        if(furi_hal_power_is_otg_enabled()) {
-            furi_hal_power_check_otg_status();
-        }
-    }
-
-    free(srv);
-    return 0;
-}

+ 1 - 1
firmware/targets/f6/ble_glue/ble_app.c

@@ -42,7 +42,7 @@ bool ble_app_init() {
     ble_app->event_flags = osEventFlagsNew(NULL);
     ble_app->event_flags = osEventFlagsNew(NULL);
     // HCI transport layer thread to handle user asynch events
     // HCI transport layer thread to handle user asynch events
     ble_app->thread = furi_thread_alloc();
     ble_app->thread = furi_thread_alloc();
-    furi_thread_set_name(ble_app->thread, "BleHciWorker");
+    furi_thread_set_name(ble_app->thread, "BleHciDriver");
     furi_thread_set_stack_size(ble_app->thread, 1024);
     furi_thread_set_stack_size(ble_app->thread, 1024);
     furi_thread_set_context(ble_app->thread, ble_app);
     furi_thread_set_context(ble_app->thread, ble_app);
     furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);
     furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);

+ 1 - 1
firmware/targets/f6/ble_glue/ble_glue.c

@@ -88,7 +88,7 @@ void ble_glue_init() {
 
 
     // FreeRTOS system task creation
     // FreeRTOS system task creation
     ble_glue->thread = furi_thread_alloc();
     ble_glue->thread = furi_thread_alloc();
-    furi_thread_set_name(ble_glue->thread, "BleShciWorker");
+    furi_thread_set_name(ble_glue->thread, "BleShciDriver");
     furi_thread_set_stack_size(ble_glue->thread, 1024);
     furi_thread_set_stack_size(ble_glue->thread, 1024);
     furi_thread_set_context(ble_glue->thread, ble_glue);
     furi_thread_set_context(ble_glue->thread, ble_glue);
     furi_thread_set_callback(ble_glue->thread, ble_glue_shci_thread);
     furi_thread_set_callback(ble_glue->thread, ble_glue_shci_thread);

+ 1 - 1
firmware/targets/f6/ble_glue/gap.c

@@ -481,7 +481,7 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
 
 
     // Thread configuration
     // Thread configuration
     gap->thread = furi_thread_alloc();
     gap->thread = furi_thread_alloc();
-    furi_thread_set_name(gap->thread, "BleGapWorker");
+    furi_thread_set_name(gap->thread, "BleGapDriver");
     furi_thread_set_stack_size(gap->thread, 1024);
     furi_thread_set_stack_size(gap->thread, 1024);
     furi_thread_set_context(gap->thread, gap);
     furi_thread_set_context(gap->thread, gap);
     furi_thread_set_callback(gap->thread, gap_app);
     furi_thread_set_callback(gap->thread, gap_app);

+ 0 - 1
firmware/targets/f6/furi_hal/furi_hal.c

@@ -38,7 +38,6 @@ void furi_hal_init() {
 
 
     // VCP + USB
     // VCP + USB
     furi_hal_usb_init();
     furi_hal_usb_init();
-    furi_hal_usb_set_config(&usb_cdc_single);
     furi_hal_vcp_init();
     furi_hal_vcp_init();
     FURI_LOG_I(TAG, "USB OK");
     FURI_LOG_I(TAG, "USB OK");
 
 

+ 168 - 91
firmware/targets/f6/furi_hal/furi_hal_usb.c

@@ -1,6 +1,7 @@
 #include "furi_hal_version.h"
 #include "furi_hal_version.h"
 #include "furi_hal_usb_i.h"
 #include "furi_hal_usb_i.h"
 #include "furi_hal_usb.h"
 #include "furi_hal_usb.h"
+#include "furi_hal_vcp.h"
 #include <furi_hal_power.h>
 #include <furi_hal_power.h>
 #include <furi.h>
 #include <furi.h>
 
 
@@ -10,29 +11,46 @@
 
 
 #define USB_RECONNECT_DELAY 500
 #define USB_RECONNECT_DELAY 500
 
 
-static FuriHalUsbInterface* usb_if_cur;
-static FuriHalUsbInterface* usb_if_next;
+typedef struct {
+    FuriThread* thread;
+    osTimerId_t tmr;
+    bool enabled;
+    bool connected;
+    FuriHalUsbInterface* if_cur;
+    FuriHalUsbInterface* if_next;
+    FuriHalUsbStateCallback callback;
+    void* cb_ctx;
+} UsbSrv;
+
+typedef enum {
+    EventModeChange = (1 << 0),
+    EventEnable = (1 << 1),
+    EventDisable = (1 << 2),
+    EventReinit = (1 << 3),
+
+    EventReset = (1 << 4),
+    EventRequest = (1 << 5),
+
+    EventModeChangeStart = (1 << 6),
+} UsbEvent;
+
+#define USB_SRV_ALL_EVENTS                                                                    \
+    (EventModeChange | EventEnable | EventDisable | EventReinit | EventReset | EventRequest | \
+     EventModeChangeStart)
+
+static UsbSrv usb;
 
 
 static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
 static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
 
 
 static uint32_t ubuf[0x20];
 static uint32_t ubuf[0x20];
 usbd_device udev;
 usbd_device udev;
 
 
-static FuriHalUsbStateCallback callback;
-static void* cb_ctx;
-
+static int32_t furi_hal_usb_thread(void* context);
 static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length);
 static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length);
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 
 
-struct UsbCfg {
-    osTimerId_t reconnect_tmr;
-    bool enabled;
-    bool connected;
-    bool mode_changing;
-} usb_config;
-
 static void furi_hal_usb_tmr_cb(void* context);
 static void furi_hal_usb_tmr_cb(void* context);
 
 
 /* Low-level init */
 /* Low-level init */
@@ -56,79 +74,51 @@ void furi_hal_usb_init(void) {
     usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt);
     usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt);
     // Reset callback will be enabled after first mode change to avoid getting false reset events
     // Reset callback will be enabled after first mode change to avoid getting false reset events
 
 
-    usb_config.enabled = false;
-    usb_config.reconnect_tmr = NULL;
+    usb.enabled = false;
+    usb.if_cur = NULL;
     HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0);
     HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0);
     NVIC_EnableIRQ(USB_LP_IRQn);
     NVIC_EnableIRQ(USB_LP_IRQn);
 
 
+    usb.thread = furi_thread_alloc();
+    furi_thread_set_name(usb.thread, "UsbDriver");
+    furi_thread_set_stack_size(usb.thread, 1024);
+    furi_thread_set_callback(usb.thread, furi_hal_usb_thread);
+    furi_thread_start(usb.thread);
+
     FURI_LOG_I(TAG, "Init OK");
     FURI_LOG_I(TAG, "Init OK");
 }
 }
 
 
 void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) {
 void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) {
-    if((new_if != usb_if_cur) && (usb_config.enabled)) { // Interface mode change - first stage
-        usb_config.mode_changing = true;
-        usb_if_next = new_if;
-        if(usb_config.reconnect_tmr == NULL)
-            usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
-        furi_hal_usb_disable();
-        usb_config.mode_changing = true;
-        osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
-    } else if(
-        (usb_config.mode_changing) &&
-        (usb_if_next != new_if)) { // Last interface mode change wasn't completed
-        osTimerStop(usb_config.reconnect_tmr);
-        usb_if_next = new_if;
-        osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
-    } else { // Interface mode change - second stage
-        if(usb_if_cur != NULL) usb_if_cur->deinit(&udev);
-        if(new_if != NULL) {
-            new_if->init(&udev, new_if);
-            usbd_reg_event(&udev, usbd_evt_reset, reset_evt);
-            FURI_LOG_I(TAG, "USB Mode change done");
-            usb_config.enabled = true;
-            usb_if_cur = new_if;
-            usb_config.mode_changing = false;
-        }
+    usb.if_next = new_if;
+    if(usb.thread == NULL) {
+        // Service thread hasn't started yet, so just save interface mode
+        return;
     }
     }
-}
-
-void furi_hal_usb_reinit() {
-    // Temporary disable callback to avoid getting false reset events
-    usbd_reg_event(&udev, usbd_evt_reset, NULL);
-    FURI_LOG_I(TAG, "USB Reinit");
-    furi_hal_usb_disable();
-    usbd_enable(&udev, false);
-    usbd_enable(&udev, true);
-    if(usb_config.reconnect_tmr == NULL)
-        usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
-    usb_config.mode_changing = true;
-    usb_if_next = usb_if_cur;
-    osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
 }
 }
 
 
 FuriHalUsbInterface* furi_hal_usb_get_config() {
 FuriHalUsbInterface* furi_hal_usb_get_config() {
-    return usb_if_cur;
+    return usb.if_cur;
 }
 }
 
 
 void furi_hal_usb_disable() {
 void furi_hal_usb_disable() {
-    if(usb_config.enabled) {
-        susp_evt(&udev, 0, 0);
-        usbd_connect(&udev, false);
-        usb_config.enabled = false;
-        FURI_LOG_I(TAG, "USB Disable");
-    }
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventDisable);
 }
 }
 
 
 void furi_hal_usb_enable() {
 void furi_hal_usb_enable() {
-    if((!usb_config.enabled) && (usb_if_cur != NULL)) {
-        usbd_connect(&udev, true);
-        usb_config.enabled = true;
-        FURI_LOG_I(TAG, "USB Enable");
-    }
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventEnable);
+}
+
+void furi_hal_usb_reinit() {
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReinit);
 }
 }
 
 
 static void furi_hal_usb_tmr_cb(void* context) {
 static void furi_hal_usb_tmr_cb(void* context) {
-    furi_hal_usb_set_config(usb_if_next);
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChangeStart);
 }
 }
 
 
 /* Get device / configuration descriptors */
 /* Get device / configuration descriptors */
@@ -137,28 +127,29 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
     const uint8_t dnumber = req->wValue & 0xFF;
     const uint8_t dnumber = req->wValue & 0xFF;
     const void* desc;
     const void* desc;
     uint16_t len = 0;
     uint16_t len = 0;
-    if(usb_if_cur == NULL) return usbd_fail;
+    if(usb.if_cur == NULL) return usbd_fail;
 
 
     switch(dtype) {
     switch(dtype) {
     case USB_DTYPE_DEVICE:
     case USB_DTYPE_DEVICE:
-        if(callback != NULL) {
-            callback(FuriHalUsbStateEventDescriptorRequest, cb_ctx);
+        osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventRequest);
+        if(usb.callback != NULL) {
+            usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.cb_ctx);
         }
         }
-        desc = usb_if_cur->dev_descr;
+        desc = usb.if_cur->dev_descr;
         break;
         break;
     case USB_DTYPE_CONFIGURATION:
     case USB_DTYPE_CONFIGURATION:
-        desc = usb_if_cur->cfg_descr;
-        len = ((struct usb_string_descriptor*)(usb_if_cur->cfg_descr))->wString[0];
+        desc = usb.if_cur->cfg_descr;
+        len = ((struct usb_string_descriptor*)(usb.if_cur->cfg_descr))->wString[0];
         break;
         break;
     case USB_DTYPE_STRING:
     case USB_DTYPE_STRING:
         if(dnumber == UsbDevLang) {
         if(dnumber == UsbDevLang) {
             desc = &dev_lang_desc;
             desc = &dev_lang_desc;
-        } else if((dnumber == UsbDevManuf) && (usb_if_cur->str_manuf_descr != NULL)) {
-            desc = usb_if_cur->str_manuf_descr;
-        } else if((dnumber == UsbDevProduct) && (usb_if_cur->str_prod_descr != NULL)) {
-            desc = usb_if_cur->str_prod_descr;
-        } else if((dnumber == UsbDevSerial) && (usb_if_cur->str_serial_descr != NULL)) {
-            desc = usb_if_cur->str_serial_descr;
+        } else if((dnumber == UsbDevManuf) && (usb.if_cur->str_manuf_descr != NULL)) {
+            desc = usb.if_cur->str_manuf_descr;
+        } else if((dnumber == UsbDevProduct) && (usb.if_cur->str_prod_descr != NULL)) {
+            desc = usb.if_cur->str_prod_descr;
+        } else if((dnumber == UsbDevSerial) && (usb.if_cur->str_serial_descr != NULL)) {
+            desc = usb.if_cur->str_serial_descr;
         } else
         } else
             return usbd_fail;
             return usbd_fail;
         break;
         break;
@@ -176,36 +167,122 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
 }
 }
 
 
 void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) {
 void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) {
-    callback = cb;
-    cb_ctx = ctx;
+    usb.callback = cb;
+    usb.cb_ctx = ctx;
 }
 }
 
 
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventReset, cb_ctx);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReset);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx);
     }
     }
 }
 }
 
 
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if((usb_if_cur != NULL) && (usb_config.connected == true)) {
-        usb_config.connected = false;
-        usb_if_cur->suspend(&udev);
+    if((usb.if_cur != NULL) && (usb.connected == true)) {
+        usb.connected = false;
+        usb.if_cur->suspend(&udev);
 
 
         furi_hal_power_insomnia_exit();
         furi_hal_power_insomnia_exit();
     }
     }
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventSuspend, cb_ctx);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventSuspend, usb.cb_ctx);
     }
     }
 }
 }
 
 
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if((usb_if_cur != NULL) && (usb_config.connected == false)) {
-        usb_config.connected = true;
-        usb_if_cur->wakeup(&udev);
+    if((usb.if_cur != NULL) && (usb.connected == false)) {
+        usb.connected = true;
+        usb.if_cur->wakeup(&udev);
 
 
         furi_hal_power_insomnia_enter();
         furi_hal_power_insomnia_enter();
     }
     }
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventWakeup, cb_ctx);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventWakeup, usb.cb_ctx);
+    }
+}
+
+static int32_t furi_hal_usb_thread(void* context) {
+    usb.tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
+
+    bool usb_request_pending = false;
+    uint8_t usb_wait_time = 0;
+
+    if(usb.if_next != NULL) {
+        osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
+    }
+
+    while(true) {
+        uint32_t flags = osThreadFlagsWait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500);
+        if((flags & osFlagsError) == 0) {
+            if(flags & EventModeChange) {
+                if(usb.if_next != usb.if_cur) {
+                    if(usb.enabled) { // Disable current interface
+                        susp_evt(&udev, 0, 0);
+                        usbd_connect(&udev, false);
+                        usb.enabled = false;
+                        osTimerStart(usb.tmr, USB_RECONNECT_DELAY);
+                    } else {
+                        flags |= EventModeChangeStart;
+                    }
+                }
+            }
+            if(flags & EventReinit) {
+                // Temporary disable callback to avoid getting false reset events
+                usbd_reg_event(&udev, usbd_evt_reset, NULL);
+                FURI_LOG_I(TAG, "USB Reinit");
+                susp_evt(&udev, 0, 0);
+                usbd_connect(&udev, false);
+                usb.enabled = false;
+
+                usbd_enable(&udev, false);
+                usbd_enable(&udev, true);
+
+                usb.if_next = usb.if_cur;
+                osTimerStart(usb.tmr, USB_RECONNECT_DELAY);
+            }
+            if(flags & EventModeChangeStart) { // Second stage of mode change process
+                if(usb.if_cur != NULL) {
+                    usb.if_cur->deinit(&udev);
+                }
+                if(usb.if_next != NULL) {
+                    usb.if_next->init(&udev, usb.if_next);
+                    usbd_reg_event(&udev, usbd_evt_reset, reset_evt);
+                    FURI_LOG_I(TAG, "USB Mode change done");
+                    usb.enabled = true;
+                    usb.if_cur = usb.if_next;
+                }
+            }
+            if(flags & EventEnable) {
+                if((!usb.enabled) && (usb.if_cur != NULL)) {
+                    usbd_connect(&udev, true);
+                    usb.enabled = true;
+                    FURI_LOG_I(TAG, "USB Enable");
+                }
+            }
+            if(flags & EventDisable) {
+                if(usb.enabled) {
+                    susp_evt(&udev, 0, 0);
+                    usbd_connect(&udev, false);
+                    usb.enabled = false;
+                    usb_request_pending = false;
+                    FURI_LOG_I(TAG, "USB Disable");
+                }
+            }
+            if(flags & EventReset) {
+                usb_request_pending = true;
+                usb_wait_time = 0;
+            }
+            if(flags & EventRequest) {
+                usb_request_pending = false;
+            }
+        } else if(usb_request_pending) {
+            usb_wait_time++;
+            if(usb_wait_time > 4) {
+                furi_hal_usb_reinit();
+                usb_request_pending = false;
+            }
+        }
     }
     }
+    return 0;
 }
 }

+ 3 - 2
firmware/targets/f6/furi_hal/furi_hal_vcp.c

@@ -1,5 +1,5 @@
 #include <furi_hal_usb_cdc_i.h>
 #include <furi_hal_usb_cdc_i.h>
-#include <furi_hal_console.h>
+#include <furi_hal.h>
 #include <furi.h>
 #include <furi.h>
 #include <stream_buffer.h>
 #include <stream_buffer.h>
 
 
@@ -65,7 +65,7 @@ void furi_hal_vcp_init() {
     vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
     vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
 
 
     vcp->thread = furi_thread_alloc();
     vcp->thread = furi_thread_alloc();
-    furi_thread_set_name(vcp->thread, "VcpWorker");
+    furi_thread_set_name(vcp->thread, "VcpDriver");
     furi_thread_set_stack_size(vcp->thread, 1024);
     furi_thread_set_stack_size(vcp->thread, 1024);
     furi_thread_set_callback(vcp->thread, vcp_worker);
     furi_thread_set_callback(vcp->thread, vcp_worker);
     furi_thread_start(vcp->thread);
     furi_thread_start(vcp->thread);
@@ -79,6 +79,7 @@ static int32_t vcp_worker(void* context) {
     size_t missed_rx = 0;
     size_t missed_rx = 0;
     uint8_t last_tx_pkt_len = 0;
     uint8_t last_tx_pkt_len = 0;
 
 
+    furi_hal_usb_set_config(&usb_cdc_single);
     furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
     furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
 
 
     while(1) {
     while(1) {

+ 1 - 1
firmware/targets/f7/ble_glue/ble_app.c

@@ -42,7 +42,7 @@ bool ble_app_init() {
     ble_app->event_flags = osEventFlagsNew(NULL);
     ble_app->event_flags = osEventFlagsNew(NULL);
     // HCI transport layer thread to handle user asynch events
     // HCI transport layer thread to handle user asynch events
     ble_app->thread = furi_thread_alloc();
     ble_app->thread = furi_thread_alloc();
-    furi_thread_set_name(ble_app->thread, "BleHciWorker");
+    furi_thread_set_name(ble_app->thread, "BleHciDriver");
     furi_thread_set_stack_size(ble_app->thread, 1024);
     furi_thread_set_stack_size(ble_app->thread, 1024);
     furi_thread_set_context(ble_app->thread, ble_app);
     furi_thread_set_context(ble_app->thread, ble_app);
     furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);
     furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);

+ 1 - 1
firmware/targets/f7/ble_glue/ble_glue.c

@@ -88,7 +88,7 @@ void ble_glue_init() {
 
 
     // FreeRTOS system task creation
     // FreeRTOS system task creation
     ble_glue->thread = furi_thread_alloc();
     ble_glue->thread = furi_thread_alloc();
-    furi_thread_set_name(ble_glue->thread, "BleShciWorker");
+    furi_thread_set_name(ble_glue->thread, "BleShciDriver");
     furi_thread_set_stack_size(ble_glue->thread, 1024);
     furi_thread_set_stack_size(ble_glue->thread, 1024);
     furi_thread_set_context(ble_glue->thread, ble_glue);
     furi_thread_set_context(ble_glue->thread, ble_glue);
     furi_thread_set_callback(ble_glue->thread, ble_glue_shci_thread);
     furi_thread_set_callback(ble_glue->thread, ble_glue_shci_thread);

+ 1 - 1
firmware/targets/f7/ble_glue/gap.c

@@ -481,7 +481,7 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
 
 
     // Thread configuration
     // Thread configuration
     gap->thread = furi_thread_alloc();
     gap->thread = furi_thread_alloc();
-    furi_thread_set_name(gap->thread, "BleGapWorker");
+    furi_thread_set_name(gap->thread, "BleGapDriver");
     furi_thread_set_stack_size(gap->thread, 1024);
     furi_thread_set_stack_size(gap->thread, 1024);
     furi_thread_set_context(gap->thread, gap);
     furi_thread_set_context(gap->thread, gap);
     furi_thread_set_callback(gap->thread, gap_app);
     furi_thread_set_callback(gap->thread, gap_app);

+ 0 - 1
firmware/targets/f7/furi_hal/furi_hal.c

@@ -38,7 +38,6 @@ void furi_hal_init() {
 
 
     // VCP + USB
     // VCP + USB
     furi_hal_usb_init();
     furi_hal_usb_init();
-    furi_hal_usb_set_config(&usb_cdc_single);
     furi_hal_vcp_init();
     furi_hal_vcp_init();
     FURI_LOG_I(TAG, "USB OK");
     FURI_LOG_I(TAG, "USB OK");
 
 

+ 168 - 91
firmware/targets/f7/furi_hal/furi_hal_usb.c

@@ -1,6 +1,7 @@
 #include "furi_hal_version.h"
 #include "furi_hal_version.h"
 #include "furi_hal_usb_i.h"
 #include "furi_hal_usb_i.h"
 #include "furi_hal_usb.h"
 #include "furi_hal_usb.h"
+#include "furi_hal_vcp.h"
 #include <furi_hal_power.h>
 #include <furi_hal_power.h>
 #include <furi.h>
 #include <furi.h>
 
 
@@ -10,29 +11,46 @@
 
 
 #define USB_RECONNECT_DELAY 500
 #define USB_RECONNECT_DELAY 500
 
 
-static FuriHalUsbInterface* usb_if_cur;
-static FuriHalUsbInterface* usb_if_next;
+typedef struct {
+    FuriThread* thread;
+    osTimerId_t tmr;
+    bool enabled;
+    bool connected;
+    FuriHalUsbInterface* if_cur;
+    FuriHalUsbInterface* if_next;
+    FuriHalUsbStateCallback callback;
+    void* cb_ctx;
+} UsbSrv;
+
+typedef enum {
+    EventModeChange = (1 << 0),
+    EventEnable = (1 << 1),
+    EventDisable = (1 << 2),
+    EventReinit = (1 << 3),
+
+    EventReset = (1 << 4),
+    EventRequest = (1 << 5),
+
+    EventModeChangeStart = (1 << 6),
+} UsbEvent;
+
+#define USB_SRV_ALL_EVENTS                                                                    \
+    (EventModeChange | EventEnable | EventDisable | EventReinit | EventReset | EventRequest | \
+     EventModeChangeStart)
+
+static UsbSrv usb;
 
 
 static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
 static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
 
 
 static uint32_t ubuf[0x20];
 static uint32_t ubuf[0x20];
 usbd_device udev;
 usbd_device udev;
 
 
-static FuriHalUsbStateCallback callback;
-static void* cb_ctx;
-
+static int32_t furi_hal_usb_thread(void* context);
 static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length);
 static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_t* length);
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
 
 
-struct UsbCfg {
-    osTimerId_t reconnect_tmr;
-    bool enabled;
-    bool connected;
-    bool mode_changing;
-} usb_config;
-
 static void furi_hal_usb_tmr_cb(void* context);
 static void furi_hal_usb_tmr_cb(void* context);
 
 
 /* Low-level init */
 /* Low-level init */
@@ -56,79 +74,51 @@ void furi_hal_usb_init(void) {
     usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt);
     usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt);
     // Reset callback will be enabled after first mode change to avoid getting false reset events
     // Reset callback will be enabled after first mode change to avoid getting false reset events
 
 
-    usb_config.enabled = false;
-    usb_config.reconnect_tmr = NULL;
+    usb.enabled = false;
+    usb.if_cur = NULL;
     HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0);
     HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0);
     NVIC_EnableIRQ(USB_LP_IRQn);
     NVIC_EnableIRQ(USB_LP_IRQn);
 
 
+    usb.thread = furi_thread_alloc();
+    furi_thread_set_name(usb.thread, "UsbDriver");
+    furi_thread_set_stack_size(usb.thread, 1024);
+    furi_thread_set_callback(usb.thread, furi_hal_usb_thread);
+    furi_thread_start(usb.thread);
+
     FURI_LOG_I(TAG, "Init OK");
     FURI_LOG_I(TAG, "Init OK");
 }
 }
 
 
 void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) {
 void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) {
-    if((new_if != usb_if_cur) && (usb_config.enabled)) { // Interface mode change - first stage
-        usb_config.mode_changing = true;
-        usb_if_next = new_if;
-        if(usb_config.reconnect_tmr == NULL)
-            usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
-        furi_hal_usb_disable();
-        usb_config.mode_changing = true;
-        osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
-    } else if(
-        (usb_config.mode_changing) &&
-        (usb_if_next != new_if)) { // Last interface mode change wasn't completed
-        osTimerStop(usb_config.reconnect_tmr);
-        usb_if_next = new_if;
-        osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
-    } else { // Interface mode change - second stage
-        if(usb_if_cur != NULL) usb_if_cur->deinit(&udev);
-        if(new_if != NULL) {
-            new_if->init(&udev, new_if);
-            usbd_reg_event(&udev, usbd_evt_reset, reset_evt);
-            FURI_LOG_I(TAG, "USB Mode change done");
-            usb_config.enabled = true;
-            usb_if_cur = new_if;
-            usb_config.mode_changing = false;
-        }
+    usb.if_next = new_if;
+    if(usb.thread == NULL) {
+        // Service thread hasn't started yet, so just save interface mode
+        return;
     }
     }
-}
-
-void furi_hal_usb_reinit() {
-    // Temporary disable callback to avoid getting false reset events
-    usbd_reg_event(&udev, usbd_evt_reset, NULL);
-    FURI_LOG_I(TAG, "USB Reinit");
-    furi_hal_usb_disable();
-    usbd_enable(&udev, false);
-    usbd_enable(&udev, true);
-    if(usb_config.reconnect_tmr == NULL)
-        usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
-    usb_config.mode_changing = true;
-    usb_if_next = usb_if_cur;
-    osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY);
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
 }
 }
 
 
 FuriHalUsbInterface* furi_hal_usb_get_config() {
 FuriHalUsbInterface* furi_hal_usb_get_config() {
-    return usb_if_cur;
+    return usb.if_cur;
 }
 }
 
 
 void furi_hal_usb_disable() {
 void furi_hal_usb_disable() {
-    if(usb_config.enabled) {
-        susp_evt(&udev, 0, 0);
-        usbd_connect(&udev, false);
-        usb_config.enabled = false;
-        FURI_LOG_I(TAG, "USB Disable");
-    }
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventDisable);
 }
 }
 
 
 void furi_hal_usb_enable() {
 void furi_hal_usb_enable() {
-    if((!usb_config.enabled) && (usb_if_cur != NULL)) {
-        usbd_connect(&udev, true);
-        usb_config.enabled = true;
-        FURI_LOG_I(TAG, "USB Enable");
-    }
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventEnable);
+}
+
+void furi_hal_usb_reinit() {
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReinit);
 }
 }
 
 
 static void furi_hal_usb_tmr_cb(void* context) {
 static void furi_hal_usb_tmr_cb(void* context) {
-    furi_hal_usb_set_config(usb_if_next);
+    furi_assert(usb.thread);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChangeStart);
 }
 }
 
 
 /* Get device / configuration descriptors */
 /* Get device / configuration descriptors */
@@ -137,28 +127,29 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
     const uint8_t dnumber = req->wValue & 0xFF;
     const uint8_t dnumber = req->wValue & 0xFF;
     const void* desc;
     const void* desc;
     uint16_t len = 0;
     uint16_t len = 0;
-    if(usb_if_cur == NULL) return usbd_fail;
+    if(usb.if_cur == NULL) return usbd_fail;
 
 
     switch(dtype) {
     switch(dtype) {
     case USB_DTYPE_DEVICE:
     case USB_DTYPE_DEVICE:
-        if(callback != NULL) {
-            callback(FuriHalUsbStateEventDescriptorRequest, cb_ctx);
+        osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventRequest);
+        if(usb.callback != NULL) {
+            usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.cb_ctx);
         }
         }
-        desc = usb_if_cur->dev_descr;
+        desc = usb.if_cur->dev_descr;
         break;
         break;
     case USB_DTYPE_CONFIGURATION:
     case USB_DTYPE_CONFIGURATION:
-        desc = usb_if_cur->cfg_descr;
-        len = ((struct usb_string_descriptor*)(usb_if_cur->cfg_descr))->wString[0];
+        desc = usb.if_cur->cfg_descr;
+        len = ((struct usb_string_descriptor*)(usb.if_cur->cfg_descr))->wString[0];
         break;
         break;
     case USB_DTYPE_STRING:
     case USB_DTYPE_STRING:
         if(dnumber == UsbDevLang) {
         if(dnumber == UsbDevLang) {
             desc = &dev_lang_desc;
             desc = &dev_lang_desc;
-        } else if((dnumber == UsbDevManuf) && (usb_if_cur->str_manuf_descr != NULL)) {
-            desc = usb_if_cur->str_manuf_descr;
-        } else if((dnumber == UsbDevProduct) && (usb_if_cur->str_prod_descr != NULL)) {
-            desc = usb_if_cur->str_prod_descr;
-        } else if((dnumber == UsbDevSerial) && (usb_if_cur->str_serial_descr != NULL)) {
-            desc = usb_if_cur->str_serial_descr;
+        } else if((dnumber == UsbDevManuf) && (usb.if_cur->str_manuf_descr != NULL)) {
+            desc = usb.if_cur->str_manuf_descr;
+        } else if((dnumber == UsbDevProduct) && (usb.if_cur->str_prod_descr != NULL)) {
+            desc = usb.if_cur->str_prod_descr;
+        } else if((dnumber == UsbDevSerial) && (usb.if_cur->str_serial_descr != NULL)) {
+            desc = usb.if_cur->str_serial_descr;
         } else
         } else
             return usbd_fail;
             return usbd_fail;
         break;
         break;
@@ -176,36 +167,122 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
 }
 }
 
 
 void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) {
 void furi_hal_usb_set_state_callback(FuriHalUsbStateCallback cb, void* ctx) {
-    callback = cb;
-    cb_ctx = ctx;
+    usb.callback = cb;
+    usb.cb_ctx = ctx;
 }
 }
 
 
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventReset, cb_ctx);
+    osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReset);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx);
     }
     }
 }
 }
 
 
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if((usb_if_cur != NULL) && (usb_config.connected == true)) {
-        usb_config.connected = false;
-        usb_if_cur->suspend(&udev);
+    if((usb.if_cur != NULL) && (usb.connected == true)) {
+        usb.connected = false;
+        usb.if_cur->suspend(&udev);
 
 
         furi_hal_power_insomnia_exit();
         furi_hal_power_insomnia_exit();
     }
     }
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventSuspend, cb_ctx);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventSuspend, usb.cb_ctx);
     }
     }
 }
 }
 
 
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
 static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
-    if((usb_if_cur != NULL) && (usb_config.connected == false)) {
-        usb_config.connected = true;
-        usb_if_cur->wakeup(&udev);
+    if((usb.if_cur != NULL) && (usb.connected == false)) {
+        usb.connected = true;
+        usb.if_cur->wakeup(&udev);
 
 
         furi_hal_power_insomnia_enter();
         furi_hal_power_insomnia_enter();
     }
     }
-    if(callback != NULL) {
-        callback(FuriHalUsbStateEventWakeup, cb_ctx);
+    if(usb.callback != NULL) {
+        usb.callback(FuriHalUsbStateEventWakeup, usb.cb_ctx);
+    }
+}
+
+static int32_t furi_hal_usb_thread(void* context) {
+    usb.tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL);
+
+    bool usb_request_pending = false;
+    uint8_t usb_wait_time = 0;
+
+    if(usb.if_next != NULL) {
+        osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
+    }
+
+    while(true) {
+        uint32_t flags = osThreadFlagsWait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500);
+        if((flags & osFlagsError) == 0) {
+            if(flags & EventModeChange) {
+                if(usb.if_next != usb.if_cur) {
+                    if(usb.enabled) { // Disable current interface
+                        susp_evt(&udev, 0, 0);
+                        usbd_connect(&udev, false);
+                        usb.enabled = false;
+                        osTimerStart(usb.tmr, USB_RECONNECT_DELAY);
+                    } else {
+                        flags |= EventModeChangeStart;
+                    }
+                }
+            }
+            if(flags & EventReinit) {
+                // Temporary disable callback to avoid getting false reset events
+                usbd_reg_event(&udev, usbd_evt_reset, NULL);
+                FURI_LOG_I(TAG, "USB Reinit");
+                susp_evt(&udev, 0, 0);
+                usbd_connect(&udev, false);
+                usb.enabled = false;
+
+                usbd_enable(&udev, false);
+                usbd_enable(&udev, true);
+
+                usb.if_next = usb.if_cur;
+                osTimerStart(usb.tmr, USB_RECONNECT_DELAY);
+            }
+            if(flags & EventModeChangeStart) { // Second stage of mode change process
+                if(usb.if_cur != NULL) {
+                    usb.if_cur->deinit(&udev);
+                }
+                if(usb.if_next != NULL) {
+                    usb.if_next->init(&udev, usb.if_next);
+                    usbd_reg_event(&udev, usbd_evt_reset, reset_evt);
+                    FURI_LOG_I(TAG, "USB Mode change done");
+                    usb.enabled = true;
+                    usb.if_cur = usb.if_next;
+                }
+            }
+            if(flags & EventEnable) {
+                if((!usb.enabled) && (usb.if_cur != NULL)) {
+                    usbd_connect(&udev, true);
+                    usb.enabled = true;
+                    FURI_LOG_I(TAG, "USB Enable");
+                }
+            }
+            if(flags & EventDisable) {
+                if(usb.enabled) {
+                    susp_evt(&udev, 0, 0);
+                    usbd_connect(&udev, false);
+                    usb.enabled = false;
+                    usb_request_pending = false;
+                    FURI_LOG_I(TAG, "USB Disable");
+                }
+            }
+            if(flags & EventReset) {
+                usb_request_pending = true;
+                usb_wait_time = 0;
+            }
+            if(flags & EventRequest) {
+                usb_request_pending = false;
+            }
+        } else if(usb_request_pending) {
+            usb_wait_time++;
+            if(usb_wait_time > 4) {
+                furi_hal_usb_reinit();
+                usb_request_pending = false;
+            }
+        }
     }
     }
+    return 0;
 }
 }

+ 3 - 2
firmware/targets/f7/furi_hal/furi_hal_vcp.c

@@ -1,5 +1,5 @@
 #include <furi_hal_usb_cdc_i.h>
 #include <furi_hal_usb_cdc_i.h>
-#include <furi_hal_console.h>
+#include <furi_hal.h>
 #include <furi.h>
 #include <furi.h>
 #include <stream_buffer.h>
 #include <stream_buffer.h>
 
 
@@ -65,7 +65,7 @@ void furi_hal_vcp_init() {
     vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
     vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
 
 
     vcp->thread = furi_thread_alloc();
     vcp->thread = furi_thread_alloc();
-    furi_thread_set_name(vcp->thread, "VcpWorker");
+    furi_thread_set_name(vcp->thread, "VcpDriver");
     furi_thread_set_stack_size(vcp->thread, 1024);
     furi_thread_set_stack_size(vcp->thread, 1024);
     furi_thread_set_callback(vcp->thread, vcp_worker);
     furi_thread_set_callback(vcp->thread, vcp_worker);
     furi_thread_start(vcp->thread);
     furi_thread_start(vcp->thread);
@@ -79,6 +79,7 @@ static int32_t vcp_worker(void* context) {
     size_t missed_rx = 0;
     size_t missed_rx = 0;
     uint8_t last_tx_pkt_len = 0;
     uint8_t last_tx_pkt_len = 0;
 
 
+    furi_hal_usb_set_config(&usb_cdc_single);
     furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
     furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
 
 
     while(1) {
     while(1) {

+ 3 - 3
lib/ST25RFAL002/platform.c

@@ -5,7 +5,7 @@
 #include <furi_hal_spi.h>
 #include <furi_hal_spi.h>
 
 
 static const osThreadAttr_t platform_irq_thread_attr = {
 static const osThreadAttr_t platform_irq_thread_attr = {
-    .name = "RfalIrqWorker",
+    .name = "RfalIrqDriver",
     .stack_size = 1024,
     .stack_size = 1024,
     .priority = osPriorityRealtime,
     .priority = osPriorityRealtime,
 };
 };
@@ -20,7 +20,7 @@ void nfc_isr(void* _ctx) {
     }
     }
 }
 }
 
 
-void platformIrqWorker() {
+void platformIrqThread() {
     while(1) {
     while(1) {
         uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever);
         uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever);
         if(flags & 0x1) {
         if(flags & 0x1) {
@@ -41,7 +41,7 @@ void platformDisableIrqCallback() {
 
 
 void platformSetIrqCallback(PlatformIrqCallback callback) {
 void platformSetIrqCallback(PlatformIrqCallback callback) {
     platform_irq_callback = callback;
     platform_irq_callback = callback;
-    platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr);
+    platform_irq_thread_id = osThreadNew(platformIrqThread, NULL, &platform_irq_thread_attr);
     hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
     hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
     // Disable interrupt callback as the pin is shared between 2 apps
     // Disable interrupt callback as the pin is shared between 2 apps
     // It is enabled in rfalLowPowerModeStop()
     // It is enabled in rfalLowPowerModeStop()