[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>
This commit is contained in:
Nikolay Minaylov 2022-07-06 16:54:08 +03:00 committed by GitHub
parent ece142a667
commit e17dae2d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 28 deletions

View File

@ -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)) {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;