diff --git a/applications/archive/helpers/archive_browser.c b/applications/archive/helpers/archive_browser.c index b2f39c07..3e4d6731 100644 --- a/applications/archive/helpers/archive_browser.c +++ b/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)) { diff --git a/applications/cli/cli.c b/applications/cli/cli.c index aa48e93b..35baad7e 100644 --- a/applications/cli/cli.c +++ b/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); diff --git a/applications/cli/cli_vcp.c b/applications/cli/cli_vcp.c index 7e23e4b1..332dd7cb 100644 --- a/applications/cli/cli_vcp.c +++ b/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); diff --git a/applications/desktop/views/desktop_view_locked.c b/applications/desktop/views/desktop_view_locked.c index 4b544988..1245c152 100644 --- a/applications/desktop/views/desktop_view_locked.c +++ b/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; diff --git a/applications/ibutton/scenes/ibutton_scene_emulate.c b/applications/ibutton/scenes/ibutton_scene_emulate.c index 9551ea90..0483b77a 100644 --- a/applications/ibutton/scenes/ibutton_scene_emulate.c +++ b/applications/ibutton/scenes/ibutton_scene_emulate.c @@ -3,6 +3,8 @@ #include #include +#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); } } diff --git a/applications/notification/notification_app.c b/applications/notification/notification_app.c index 687672c9..9f362358 100644 --- a/applications/notification/notification_app.c +++ b/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); } diff --git a/core/furi/thread.c b/core/furi/thread.c index 692e5e05..266a3855 100644 --- a/core/furi/thread.c +++ b/core/furi/thread.c @@ -7,6 +7,8 @@ #include #include +#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;