Просмотр исходного кода

[FL-2612, FL-2618, FL-2619, FL-2622] CLI, threads, notifications, archive fixes (#1354)

* CLI, notifications, archive fixes
* Led blink fix
* Fix thread flags notification index
* Archive: fix infinite tab switch on empty SD card

Co-authored-by: あく <alleteam@gmail.com>
Nikolay Minaylov 3 лет назад
Родитель
Сommit
e17dae2d00

+ 27 - 6
applications/archive/helpers/archive_browser.c

@@ -15,8 +15,9 @@ static void
 
     int32_t load_offset = 0;
     browser->is_root = is_root;
+    ArchiveTabEnum tab = archive_get_tab(browser);
 
-    if((item_cnt == 0) && (archive_is_home(browser))) {
+    if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) {
         archive_switch_tab(browser, browser->last_tab_switch_dir);
     } else if(!string_start_with_str_p(browser->path, "/app:")) {
         with_view_model(
@@ -389,6 +390,22 @@ void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
         });
 }
 
+static bool archive_is_dir_exists(string_t path) {
+    if(string_equal_str_p(path, "/any")) {
+        return true;
+    }
+    bool state = false;
+    FileInfo file_info;
+    Storage* storage = furi_record_open("storage");
+    if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) {
+        if(file_info.flags & FSF_DIRECTORY) {
+            state = true;
+        }
+    }
+    furi_record_close("storage");
+    return state;
+}
+
 void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
     furi_assert(browser);
     ArchiveTabEnum tab = archive_get_tab(browser);
@@ -418,11 +435,15 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
             }
         }
     } else {
-        ArchiveTabEnum tab = archive_get_tab(browser);
-        bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true;
-        file_browser_worker_set_config(
-            browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets);
-        tab_empty = false; // Empty check will be performed later
+        tab = archive_get_tab(browser);
+        if(archive_is_dir_exists(browser->path)) {
+            bool skip_assets = (strcmp(archive_get_tab_ext(tab), "*") == 0) ? false : true;
+            file_browser_worker_set_config(
+                browser->worker, browser->path, archive_get_tab_ext(tab), skip_assets);
+            tab_empty = false; // Empty check will be performed later
+        } else {
+            tab_empty = true;
+        }
     }
 
     if((tab_empty) && (tab != ArchiveTabBrowser)) {

+ 8 - 4
applications/cli/cli.c

@@ -229,18 +229,22 @@ static void cli_handle_enter(Cli* cli) {
 
     // Search for command
     furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK);
-    CliCommand* cli_command = CliCommandTree_get(cli->commands, command);
-    if(cli_command) {
+    CliCommand* cli_command_ptr = CliCommandTree_get(cli->commands, command);
+
+    if(cli_command_ptr) {
+        CliCommand cli_command;
+        memcpy(&cli_command, cli_command_ptr, sizeof(CliCommand));
+        furi_check(osMutexRelease(cli->mutex) == osOK);
         cli_nl(cli);
-        cli_execute_command(cli, cli_command, args);
+        cli_execute_command(cli, &cli_command, args);
     } else {
+        furi_check(osMutexRelease(cli->mutex) == osOK);
         cli_nl(cli);
         printf(
             "`%s` command not found, use `help` or `?` to list all available commands",
             string_get_cstr(command));
         cli_putc(cli, CliSymbolAsciiBell);
     }
-    furi_check(osMutexRelease(cli->mutex) == osOK);
 
     cli_reset(cli);
     cli_prompt(cli);

+ 1 - 0
applications/cli/cli_vcp.c

@@ -199,6 +199,7 @@ static int32_t vcp_worker(void* context) {
             furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL, NULL);
             // Restore previous USB mode (if it was set during init)
             if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) {
+                furi_hal_usb_unlock();
                 furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
             }
             xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);

+ 7 - 5
applications/desktop/views/desktop_view_locked.c

@@ -158,7 +158,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
     const bool pin_locked = model->pin_locked;
     view_commit_model(locked_view->view, is_changed);
 
-    if(view_state == DesktopViewLockedStateUnlocked || event->type != InputTypeShort) {
+    if(view_state == DesktopViewLockedStateUnlocked) {
         return view_state != DesktopViewLockedStateUnlocked;
     } else if(view_state == DesktopViewLockedStateLocked && pin_locked) {
         locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
@@ -173,10 +173,12 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
         desktop_view_locked_update_hint_icon_timeout(locked_view);
 
         if(event->key == InputKeyBack) {
-            locked_view->lock_lastpress = press_time;
-            locked_view->lock_count++;
-            if(locked_view->lock_count == UNLOCK_CNT) {
-                locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
+            if(event->type == InputTypeShort) {
+                locked_view->lock_lastpress = press_time;
+                locked_view->lock_count++;
+                if(locked_view->lock_count == UNLOCK_CNT) {
+                    locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
+                }
             }
         } else {
             locked_view->lock_count = 0;

+ 15 - 1
applications/ibutton/scenes/ibutton_scene_emulate.c

@@ -3,6 +3,8 @@
 #include <dolphin/dolphin.h>
 #include <toolbox/path.h>
 
+#define EMULATE_TIMEOUT_TICKS 10
+
 static void ibutton_scene_emulate_callback(void* context, bool emulated) {
     iButton* ibutton = context;
     if(emulated) {
@@ -95,11 +97,23 @@ bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) {
     bool consumed = false;
 
     if(event.type == SceneManagerEventTypeTick) {
+        uint32_t cnt = scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate);
+        if(cnt > 0) {
+            cnt--;
+            if(cnt == 0) {
+                ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink);
+            }
+            scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneEmulate, cnt);
+        }
         consumed = true;
     } else if(event.type == SceneManagerEventTypeCustom) {
         consumed = true;
         if(event.event == iButtonCustomEventWorkerEmulated) {
-            ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink);
+            if(scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate) == 0) {
+                ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink);
+            }
+            scene_manager_set_scene_state(
+                ibutton->scene_manager, iButtonSceneEmulate, EMULATE_TIMEOUT_TICKS);
         }
     }
 

+ 10 - 4
applications/notification/notification_app.c

@@ -93,6 +93,9 @@ void notification_reset_notification_led_layer(NotificationLedLayer* layer) {
 }
 
 void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) {
+    if(reset_mask & reset_blink_mask) {
+        furi_hal_light_blink_stop();
+    }
     if(reset_mask & reset_red_mask) {
         notification_reset_notification_led_layer(&app->led[0]);
     }
@@ -102,9 +105,6 @@ void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_m
     if(reset_mask & reset_blue_mask) {
         notification_reset_notification_led_layer(&app->led[2]);
     }
-    if(reset_mask & reset_blink_mask) {
-        furi_hal_light_blink_stop();
-    }
     if(reset_mask & reset_vibro_mask) {
         notification_vibro_off();
     }
@@ -243,6 +243,9 @@ void notification_process_notification_message(
                 notification_message->data.led_blink.on_time,
                 notification_message->data.led_blink.period);
             reset_mask |= reset_blink_mask;
+            reset_mask |= reset_red_mask;
+            reset_mask |= reset_green_mask;
+            reset_mask |= reset_blue_mask;
             break;
         case NotificationMessageTypeLedBlinkColor:
             led_active = true;
@@ -251,6 +254,9 @@ void notification_process_notification_message(
         case NotificationMessageTypeLedBlinkStop:
             furi_hal_light_blink_stop();
             reset_mask &= ~reset_blink_mask;
+            reset_mask |= reset_red_mask;
+            reset_mask |= reset_green_mask;
+            reset_mask |= reset_blue_mask;
             break;
         case NotificationMessageTypeVibro:
             if(notification_message->data.vibro.on) {
@@ -326,7 +332,7 @@ void notification_process_notification_message(
         reset_mask |= reset_green_mask;
         reset_mask |= reset_blue_mask;
 
-        if(need_minimal_delay) {
+        if((need_minimal_delay) && (reset_notifications)) {
             notification_apply_notification_leds(app, led_off_values);
             furi_hal_delay_ms(minimal_delay);
         }

+ 14 - 8
core/furi/thread.c

@@ -7,6 +7,8 @@
 #include <task.h>
 #include <m-string.h>
 
+#define THREAD_NOTIFY_INDEX 1 // Index 0 is used for stream buffers
+
 struct FuriThread {
     FuriThreadState state;
     int32_t ret;
@@ -221,13 +223,14 @@ uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags) {
         if(FURI_IS_IRQ_MODE()) {
             yield = pdFALSE;
 
-            (void)xTaskNotifyFromISR(hTask, flags, eSetBits, &yield);
-            (void)xTaskNotifyAndQueryFromISR(hTask, 0, eNoAction, &rflags, NULL);
+            (void)xTaskNotifyIndexedFromISR(hTask, THREAD_NOTIFY_INDEX, flags, eSetBits, &yield);
+            (void)xTaskNotifyAndQueryIndexedFromISR(
+                hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags, NULL);
 
             portYIELD_FROM_ISR(yield);
         } else {
-            (void)xTaskNotify(hTask, flags, eSetBits);
-            (void)xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags);
+            (void)xTaskNotifyIndexed(hTask, THREAD_NOTIFY_INDEX, flags, eSetBits);
+            (void)xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags);
         }
     }
     /* Return flags after setting */
@@ -245,11 +248,13 @@ uint32_t furi_thread_flags_clear(uint32_t flags) {
     } else {
         hTask = xTaskGetCurrentTaskHandle();
 
-        if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &cflags) == pdPASS) {
+        if(xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &cflags) ==
+           pdPASS) {
             rflags = cflags;
             cflags &= ~flags;
 
-            if(xTaskNotify(hTask, cflags, eSetValueWithOverwrite) != pdPASS) {
+            if(xTaskNotifyIndexed(hTask, THREAD_NOTIFY_INDEX, cflags, eSetValueWithOverwrite) !=
+               pdPASS) {
                 rflags = (uint32_t)osError;
             }
         } else {
@@ -270,7 +275,8 @@ uint32_t furi_thread_flags_get(void) {
     } else {
         hTask = xTaskGetCurrentTaskHandle();
 
-        if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags) != pdPASS) {
+        if(xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags) !=
+           pdPASS) {
             rflags = (uint32_t)osError;
         }
     }
@@ -300,7 +306,7 @@ uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeo
 
         t0 = xTaskGetTickCount();
         do {
-            rval = xTaskNotifyWait(0, clear, &nval, tout);
+            rval = xTaskNotifyWaitIndexed(THREAD_NOTIFY_INDEX, 0, clear, &nval, tout);
 
             if(rval == pdPASS) {
                 rflags &= flags;